Cruce de ficheros con Joinkeys avanzado

En un artículo anterior vimos un ejemplo de Joinkeys en su forma más básica. A continuación vamos a introducir el resto de posibilidades que ofrece esta aplicación que se ejecuta dentro de la utilidad sort del mainframe (tanto DFSORT como su clon Syncsort)

JNF1CNTL Y JNF2CNTL: DD para incluir sentencias de control (INCLUDE, OMIT, INREC y SUM) para los ficheros 1 y 2 respectivamente.

SORTED: Indica que el fichero de entrada se encuentra ordenado y no es necesario el proceso de ordenación.

JOIN: Permite especificar el tipo de cruce. Si no la incluimos, se hará el cruce básico que vimos en el ejemplo anterior, que genera un fichero con los registros que cruzan. Las otras opciones son:

  • UNPAIRED,F1,ONLY

Solo los registros del fichero 1 que no cruzan.

  • UNPAIRED,F2,ONLY

Solo los registros del fichero 2 que no cruzan.

  • UNPAIRED,F1

Registros que cruzan más registros del fichero 1 que no cruzan.

  • UNPAIRED,F2

Registros que cruzan más registros del fichero 2 que no cruzan.

  • UNPAIRED,F1,F2 o UNPAIRED

Registros que cruzan más registros que no cruzan de ambos ficheros de entrada.

  • UNPAIRED,F1,F2 ONLY o UNPAIRED ONLY

Solo los registros que no cruzan de ambos ficheros de entrada.

Para ver un caso de utilización de estas nuevas opciones, vamos a incluirlas en el ejemplo del artículo anterior sobre enfrentamiento. Recordamos que se trataba de dos ficheros de entrada de 10 posiciones con la clave en las 3 primeras. El primero de ellos contenía nombres de personas y el segundo teléfonos. Cuando las claves de los ficheros 1 y 2 coincidían queríamos escribir en salida un registro con la clave, el nombre y el teléfono.

Ahora sabemos que los ficheros de entrada están ordenados, por lo que usamos la opción SORTED, que evita la ordenación inicial. En salida queremos obtener no solo los registros que cruzan sino también los no emparejados de ambos ficheros (por ejemplo, para llevar un control de errores). Para ello empleamos la opción UNPAIRED,F1,F2. Además queremos aplicar un filtro sobre el segundo fichero de entrada para que solo entren en el cruce los teléfonos que empiecen por 9. Lo indicaremos mediante la DD JNF2CNTL.

Para poder identificar la procedencia de los registros de salida, hay que añadirle el carácter de control ‘?’ al fichero de cruce. El proceso de cruce informará el caracter de control con ‘1’, ‘2’ o ‘B’ dependiendo de si la clave se encuentra solo en el fichero 1, solo en el 2 o en ambos.

Una vez realizado el cruce, el fichero generado pasa por nuevo sort en el que podemos reordenar el fichero de salida, formatearlo, etc. En el ejemplo no lo ordenamos (SORT FIELDS=COPY) , pero añadimos tres sentencias OUTFIL para generar tres ficheros diferentes en función de la procedencia (cruzan, solo en fichero 1 y solo en fichero 2)

//CRUCE  EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTJNF1 DD DSN=ENTRADA1,DISP=SHR
//SORTJNF2 DD DSN=ENTRADA2,DISP=SHR
//F1SOLO   DD DSN=SALIDA1,
//            DISP=(,CATLG,DELETE),SPACE=(TRK,(1,1),RLSE),
//            DCB=(RECFM=FB,LRECL=10,BLKSIZE=0)
//F2SOLO   DD DSN=SALIDA2,
//            DISP=(,CATLG,DELETE),SPACE=(TRK,(1,1),RLSE),
//            DCB=(RECFM=FB,LRECL=10,BLKSIZE=0)
//AMBOS    DD DSN=SALIDA3,
//            DISP=(,CATLG,DELETE),SPACE=(TRK,(1,1),RLSE),
//            DCB=(RECFM=FB,LRECL=17,BLKSIZE=0)
//JNF2CNTL  DD *
  INCLUDE COND=(4,1,CH,EQ,C'9')
//SYSIN DD *
  JOINKEYS FILE=F1,FIELDS=(1,3,A),SORTED
  JOINKEYS FILE=F2,FIELDS=(1,3,A),SORTED
  JOIN UNPAIRED,F1,F2
  REFORMAT FIELDS=(F1:1,10,F2:1,10,?)
* ‘?’: carácter de control para distinguir los registros de salida
*    ‘1’: solo en fichero 1 
*    ‘2’: solo en fichero 2
*    ‘B’: en ambos 
  SORT FIELDS=COPY
  OUTFIL FNAMES=F1SOLO,INCLUDE=(21,1,CH,EQ,C'1'),
  BUILD=(1,10)
  OUTFIL FNAMES=F2SOLO,INCLUDE=(21,1,CH,EQ,C'2'),
  BUILD=(11,10)
  OUTFIL FNAMES=AMBOS,INCLUDE=(21,1,CH,EQ,C'B'),
  BUILD=(1,10,14,7)



8 comentarios sobre Cruce de ficheros con Joinkeys avanzado

  • Paideia

    Hola.

    Una duda, Y en caso de que en algún momento el JOINKEYS de error ¿sabremos en que punto/registro ha fallado?, ¿se podría controlar el errro?

    Un saludo y gracias.

    • Hola,

      El único error de ejecución propio de JOINKEYS que conozco es este:

      ICE424A ddname (Fn) KEY IS OUT OF
      SEQUENCE

      Se produce cuando utilizamos el parámetro SORTED sin la opción NOSEQCK y el fichero no está ordenado.

      Creo que no indica el registro en el que se ha encontrado el problema, pero para solucionarlo.basta con quitar el parámetro SORTED para que se haga una ordenación del fichero antes del cruce.

      Si lo que hacemos es incluir la opción NOSEQCK, el JOINKEYS terminará sin error, pero los resultados son imprevisibles porque realmente no estaremos haciendo un cruce al no estar ordenado uno de ficheros.

      Por supuesto, en un JOINKEYS nos podemos encontrar con los errores propios de cualquier Sort: sintácticos, al especificar las posiciones del fichero o de ejecución.

  • Esther

    Hola,

    ¿Podríais ayudarme a resolver este error? Estoy cruzando dos ficheros y para algunos registros si se están cruzando correctamente las claves pero para otros, a pesar de que coinciden las claves, es como si no coincidiesen.

    Los ficheros de entrada son VB, están ordenados y la relación de registros es N:1. ¿Puede ser por eso? ¿Es necesario que sea 1:1?

    //JOIN01 EXEC PGM=SORT,COND=(0,NE)
    //ENTRADA1 DD DSN=FICHEROENTRADA1,DISP=SHR
    //ENTRADA2 DD DSN=FICHEROENTRADA2,DISP=SHR
    //SORTOUT DD DSN=FICHEROSALIDA,
    // DISP=(,CATLG,DELETE),SPACE=(CYL,(50,50),RLSE)
    //SYSOUT DD SYSOUT=*
    //SYSIN DD *
    JOINKEYS F1=ENTRADA1,FIELDS=(32,6,A,5,17,A,229,18,A,119,19,A),
    SORTED,NOSEQCK,TYPE=V
    JOINKEYS F2=ENTRADA2,FIELDS=(81,6,A,49,17,A,5,18,A,23,19,A),
    SORTED,NOSEQCK,TYPE=V
    JOIN UNPAIRED,F1
    REFORMAT FIELDS=(F1:5,160,F2:167,9,F1:174,4068)
    SORT FIELDS=COPY

    Muchas gracias.

    • Hola,

      Ten en cuenta que los campos de cruce se tratan como binarios.

      Puede ocurrir que estés cruzando algún campo numérico con signo con un numérico sin signo. En ese caso, los campos de cruce contendrán el mismo valor, pero almacenado de forma diferente.

      Por ejemplo, un numérico sin signo de 5 posiciones con valor 123(PIC 9(5) en COBOL) contendrá el valor hexadecimal F0F0F1F2F3. Mientras que en un númerico con signo (PIC S9(5)), el mismo valor se almacenará como F0F0F1F2C3.

      Si es tu problema, tendrías que convertir previamente todos los numéricos al mismo formato (con o sin signo). Puedes hacerlo en el propio JOINKEYS, usando las fichas SORTJNF1 o SORTJNF2, o con otro sort previo.

      • Esther

        Muchas gracias. He quitado en la clave de cruce las primeras 6 posiciones, que realmente no las necesitaba, y ya funciona. De todos modos me apunto lo de SORTJNF1, no lo conocía.

  • joselu

    Hola
    Lo que yo quiero hacer en un cruce de ficheros de este tipo es que si cruzan mueva un campo de F2 a un campo de F1 para sacar en salida F1 con ese campo de F2. Esto lo sé hacer pero no sé cómo hacer en el caso de que no crucen pues tendría que dejar el campo de F1 con valor cero.

  • admin

    Hola,
    Para evitar ese problema tienes que filtrar por el carácter de control, como en el ejemplo.
    OUTFIL FNAMES=AMBOS,INCLUDE=(21,1,CH,EQ,C’B’),
    BUILD=(1,10,14,7)
    En este fichero solo vas a tener los registros que crucen, por tanto tendrás informadas tanto las posiciones que vienen del fichero 1 como del 2.

  • hola necesito una ayuda estoy tratando de hacer un joinkeys dos archivos con la misma llave pero me esta generado error ABENDU0016
    PASO0000 EXEC PGM=SORT,COND=(0,LT)
    SORTJNF1 DD DSN=NALD.PE.BAT1UNLO.PETC001.UNLOAD.D161202,
    DISP=SHR
    SORTJNF2 DD DSN=NALD.UG.UWJE881D.UW4CI801.ENDE.F161202,
    DISP=SHR
    SORTOUT DD DSN=NALD.RC.RJEIEN0.BAT1STEN.SORT1.F161202,
    DISP=(NEW,CATLG,DELETE),UNIT=SYSALLDA,
    SPACE=(CYL,(25,25),RLSE),
    DCB=(LRECL=24,BLKSIZE=0,RECFM=FB)
    SYSPRINT DD SYSOUT=*
    SYSOUT DD SYSOUT=*
    SYSIN DD *
    JOINKEYS F1=SORTJNF1,FIELDS=(13,2,A,16,11,A)
    JOINKEYS F2=SORTJNF2,FIELDS=(24,2,A,28,11,A)
    SORT FIELDS=(13,2,CH,A,16,11,CH,A)
    SUM FIELDS=NONE
    REFORMAT FIELDS=(F1:13,2,16,11,F2:28,11)
    END
    agradeceria su colaboracion

Deja un comentario