1. SUM FIELDS — agregação e deduplicação

O SUM FIELDS opera sobre registros com a mesma chave de ordenação. Ele soma os campos numéricos indicados e mantém apenas um registro por chave — o que equivale a um GROUP BY + SUM do SQL.

/* Somar valores por chave (posição 1-5) e eliminar duplicatas */ SORT FIELDS=(1,5,CH,A) SUM FIELDS=(11,7,ZD) /* somar campo numérico na pos 11, 7 bytes ZD */

Com esse JCL, se houver dois registros com a mesma chave (posição 1-5), o SORT mantém um único registro com a soma dos valores na posição 11-17.

/* Deduplicar sem somar — eliminar registros duplicados pela chave */ SORT FIELDS=(1,5,CH,A) SUM FIELDS=NONE

SUM FIELDS=NONE elimina os registros com chave duplicada, mantendo apenas o primeiro de cada grupo — sem somar nada. É o equivalente de um SELECT DISTINCT por chave.

⚠️ SUM exige SORT — não funciona com FIELDS=COPY

O SUM só faz sentido quando os registros foram ordenados pela chave — o SORT precisa agrupar registros adjacentes com a mesma chave para somá-los. Por isso, SUM não pode ser usado com SORT FIELDS=COPY.

2. INREC — reformatando antes de ordenar

O INREC reformata cada registro de entrada antes que ele seja ordenado. É útil quando você precisa reorganizar campos para que a chave de ordenação fique na posição certa, ou para calcular um campo derivado que será usado como chave.

/* Reorganizar registro: colocar data (pos 40-47) no início */ SORT FIELDS=(1,8,CH,A,9,30,CH,A) INREC FIELDS=(40,8,1,39) /* data primeiro, depois resto */ OUTREC FIELDS=(9,39) /* saída sem a data no início */

🦕 Analogia — INREC/OUTREC como rascunho e versão final

Pense no INREC como uma etapa de preparação: você reorganiza o registro internamente para facilitar a ordenação. O OUTREC é a etapa final: você define como o registro vai para o SORTOUT. O registro que passa pelo SORT internamente pode ser diferente do que entra e do que sai.

3. OUTFIL — múltiplos arquivos de saída

Com OUTFIL, um único passo de SORT pode gerar vários arquivos de saída diferentes — cada um com seu próprio filtro e formato. Isso elimina múltiplos steps de SORT quando você precisa segmentar um arquivo.

//* Um SORT que gera 3 arquivos: SP, RJ e outros estados //ORDENAR EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=USUARIO.CLIENTES,DISP=SHR //SAIDA1 DD DSN=USUARIO.CLIENTES.SP, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(5,2)), // DCB=(RECFM=FB,LRECL=80) //SAIDA2 DD DSN=USUARIO.CLIENTES.RJ, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(5,2)), // DCB=(RECFM=FB,LRECL=80) //SAIDA3 DD DSN=USUARIO.CLIENTES.OUTROS, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(10,5)), // DCB=(RECFM=FB,LRECL=80) //SYSIN DD * SORT FIELDS=(1,30,CH,A) OUTFIL FNAMES=SAIDA1,INCLUDE=(31,2,CH,EQ,C'SP') OUTFIL FNAMES=SAIDA2,INCLUDE=(31,2,CH,EQ,C'RJ') OUTFIL FNAMES=SAIDA3,OMIT=(31,2,CH,EQ,C'SP',OR, 31,2,CH,EQ,C'RJ') /*

Cada OUTFIL referencia um DD pelo nome em FNAMES= e pode ter seu próprio INCLUDE, OMIT e OUTREC. O SORTOUT não é usado quando se usa OUTFIL — os DDs do OUTFIL substituem o SORTOUT.

4. JOINKEYS — juntando dois arquivos

O JOINKEYS faz o equivalente de um JOIN SQL entre dois arquivos, usando um campo-chave comum. É um dos recursos mais poderosos do DFSORT para processos de ETL.

//* Juntar arquivo de pedidos (F1) com arquivo de clientes (F2) //* usando código de cliente como chave (pos 1-8 em ambos) //JOINPASSO EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTJNF1 DD DSN=USUARIO.PEDIDOS,DISP=SHR /* arquivo 1 (F1) */ //SORTJNF2 DD DSN=USUARIO.CLIENTES,DISP=SHR /* arquivo 2 (F2) */ //SORTOUT DD DSN=USUARIO.RESULTADO, // DISP=(NEW,CATLG,DELETE), // SPACE=(TRK,(20,10)), // DCB=(RECFM=FB,LRECL=120) //SYSIN DD * JOINKEYS FILES=F1,FIELDS=(1,8,A) /* chave no F1: pos 1, 8 bytes */ JOINKEYS FILES=F2,FIELDS=(1,8,A) /* chave no F2: pos 1, 8 bytes */ JOIN UNPAIRED,F1 /* INNER JOIN (só pares) */ REFORMAT FIELDS=(F1:1,80,F2:9,40) /* montar registro de saída */ /*

O REFORMAT FIELDS define como montar o registro de saída, referenciando campos de F1 e F2 com a notação F1:posição,comprimento e F2:posição,comprimento.

Tipos de JOIN

Instrução JOINEquivalente SQLO que inclui na saída
JOIN UNPAIRED,F1LEFT JOINTodos de F1, com ou sem par em F2
JOIN UNPAIRED,F2RIGHT JOINTodos de F2, com ou sem par em F1
JOIN UNPAIRED,F1,F2FULL OUTER JOINTodos de F1 e F2
(sem UNPAIRED)INNER JOINApenas registros com par nos dois arquivos

5. Exemplo real — relatório de vendas por filial

Juntando o que aprendemos: um SORT que filtra transações do mês corrente, soma o valor por filial e gera dois arquivos — um com filiais acima da meta e outro abaixo.

//RELATORIO EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=USUARIO.TRANSACOES,DISP=SHR //ACIMA DD DSN=USUARIO.FILIAIS.ACIMA, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(5,2)), // DCB=(RECFM=FB,LRECL=12) //ABAIXO DD DSN=USUARIO.FILIAIS.ABAIXO, // DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(5,2)), // DCB=(RECFM=FB,LRECL=12) //SYSIN DD * SORT FIELDS=(1,4,CH,A) /* ordenar por código filial */ INCLUDE COND=(5,6,ZD,EQ,202606) /* apenas junho/2026 */ SUM FIELDS=(11,8,ZD) /* somar valor por filial */ OUTREC FIELDS=(1,4,11,8) /* só cód e valor total */ OUTFIL FNAMES=ACIMA,INCLUDE=(5,8,ZD,GE,50000) /* meta=50000 */ OUTFIL FNAMES=ABAIXO,OMIT=(5,8,ZD,GE,50000) /*

✅ OUTFIL opera após o SUM e OUTREC

A sequência de processamento interna do SORT é: INREC → INCLUDE/OMIT → SORT → SUM → OUTREC → OUTFIL. Isso significa que o OUTFIL vê o registro já transformado pelo OUTREC. No exemplo acima, o OUTFIL usa posição 5 porque no registro reformatado pelo OUTREC o valor já está na posição 5 (após os 4 bytes do código de filial).