A comprehensive guide to data sorting and manipulation
SORT/DFSORT (Data Facility Sort) is a high-performance sorting, merging, and copying tool for z/OS environments. Beyond basic sorting operations, DFSORT provides extensive data manipulation capabilities, allowing you to filter, reformat, summarize, and analyze data during processing.
DFSORT is primarily used for:
To use DFSORT, you need to specify the following in your JCL:
Basic DFSORT JCL template:
12345678//SORTSTEP EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=INPUT.DATASET,DISP=SHR //SORTOUT DD DSN=OUTPUT.DATASET,DISP=(NEW,CATLG,DELETE), // SPACE=(CYL,(5,2)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=27920) //SYSIN DD * SORT FIELDS=(1,10,CH,A) /*
The SORT statement defines the sorting operation:
1SORT FIELDS=(p1,m1,f1,s1,p2,m2,f2,s2,...)
Where:
Sort by character field in positions 1-10 ascending:
1SORT FIELDS=(1,10,CH,A)
Sort by multiple fields (positions 20-25 descending, then 1-5 ascending):
1SORT FIELDS=(20,6,CH,D,1,5,CH,A)
Sort by packed decimal field in positions 10-12:
1SORT FIELDS=(10,3,PD,A)
The INCLUDE and EXCLUDE statements allow you to filter records based on conditions:
12INCLUDE COND=(p1,m1,f1,operator,constant) EXCLUDE COND=(p1,m1,f1,operator,constant)
Where operators include:
Include only records with 'DEPT10' in positions 1-6:
1INCLUDE COND=(1,6,CH,EQ,C'DEPT10')
Include records with numeric value greater than 100 in packed decimal format:
1INCLUDE COND=(25,4,PD,GT,+100)
Complex condition with AND/OR logic:
123INCLUDE COND=(1,3,CH,EQ,C'ABC',AND, 10,5,CH,EQ,C'12345',OR, 20,2,BI,GT,X'0064')
INREC reformats records before sorting, while OUTREC reformats after sorting. Both statements allow you to rearrange fields, remove unwanted data, insert constants, and perform calculations.
Copy specific fields to create a new record layout:
1234OUTREC FIELDS=(1,10, /* Copy positions 1-10 */ 15,5, /* Copy positions 15-19 */ C'CONSTANT', /* Insert literal */ 35,10) /* Copy positions 35-44 */
Perform calculations and format numeric fields:
1234OUTREC FIELDS=(1,20, /* Copy name field */ 25,4,ZD,TO=PD,LENGTH=3, /* Convert ZD to PD */ 45,6,PD,TO=ZD,LENGTH=10, /* Convert PD to ZD with leading zeros */ 52,5,ZD,TO=FS,LENGTH=7) /* Format as signed numeric */
Convert dates between formats:
123INREC FIELDS=(1,20, 21,8,Y4T,TOJUL=Y4T, /* Convert YYYYMMDD to YYYYDDD */ 45,7,Y4T,TOGREG=MDY) /* Convert YYYYDDD to MM/DD/YYYY */
The SUM statement allows you to combine records with matching keys by adding specified numeric fields. This is particularly useful for creating subtotals and totals.
1234SORT FIELDS=(1,10,CH,A) /* Sort by key field */ SUM FIELDS=(25,4,ZD, /* Add field in positions 25-28 */ 35,6,PD, /* Add field in positions 35-40 */ NONE) /* No additional control fields */
When using SUM:
ICETOOL is an enhanced DFSORT utility that provides additional capabilities through a set of operators. It simplifies many common tasks and provides enhanced reporting features.
Key ICETOOL operators:
1234567891011121314151617//TOOLSTEP EXEC PGM=ICETOOL //TOOLMSG DD SYSOUT=* //DFSMSG DD SYSOUT=* //SORTIN DD DSN=INPUT.DATASET,DISP=SHR //SORTOUT DD DSN=OUTPUT.DATASET,DISP=(NEW,CATLG), // SPACE=(CYL,(5,2)),DCB=(RECFM=FB,LRECL=80) //REPORT DD SYSOUT=* //TOOLIN DD * DISPLAY FROM(SORTIN) LIST(REPORT) - TITLE('Employee Department Report') - HEADER('EMPLOYEE') HEADER('DEPARTMENT') HEADER('SALARY') - FIELDS=(5,20,CH,1,4,CH,25,10,ZD,E'$$$,$$$,$$9.99') SORT FROM(SORTIN) TO(SORTOUT) USING(CTL1) //CTL1CNTL DD * SORT FIELDS=(1,4,CH,A) INCLUDE COND=(25,10,ZD,GT,+50000) /*
123456789//SORT01 EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=EMPLOYEE.DATA,DISP=SHR //SORTOUT DD DSN=EMPLOYEE.SORTED,DISP=(NEW,CATLG), // SPACE=(CYL,(1,1)),DCB=(RECFM=FB,LRECL=80) //SYSIN DD * SORT FIELDS=(10,20,CH,A,1,9,CH,A) INCLUDE COND=(5,2,CH,EQ,C'10',OR,5,2,CH,EQ,C'20') /*
This example sorts employee records by name (positions 10-29) and then by employee ID (positions 1-9). It includes only employees from departments 10 and 20.
123456789101112131415161718//SORT02 EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=SALES.DATA,DISP=SHR //SORTOUT DD SYSOUT=* //SYSIN DD * SORT FIELDS=(1,5,CH,A,10,8,PD,D) INCLUDE COND=(30,6,PD,GT,+10000) OUTREC FIELDS=(1,5, /* Region Code */ X'40', /* Space */ 10,8,PD,TO=ZD, /* Sales Amount as ZD */ X'40', /* Space */ 30,6,PD,TO=ZD, /* Quantity as ZD */ X'40', /* Space */ C'Report Generated on ', DATE=(DMY,4-), /* Current Date DD/MM/YYYY */ X'40', /* Space */ TIME) /* Current Time HH:MM:SS */ /*
This example creates a formatted report of sales data. It sorts by region and descending sales amount, includes only records with quantities greater than 10,000, and reformats the output with descriptive text and current date/time.
123456789101112131415161718//SORT03 EXEC PGM=SORT //SYSOUT DD SYSOUT=* //SORTIN DD DSN=MONTHLY.SALES,DISP=SHR //SORTOUT DD DSN=SALES.SUMMARY,DISP=(NEW,CATLG), // SPACE=(CYL,(1,1)),DCB=(RECFM=FB,LRECL=50) //SYSIN DD * SORT FIELDS=(1,5,CH,A,6,4,CH,A) /* Region, Department */ SUM FIELDS=(10,4,ZD, /* Quantity */ 15,8,PD, /* Amount */ NONE) OUTREC FIELDS=(1,5, /* Region */ X'40', /* Space */ 6,4, /* Department */ X'40', /* Space */ 10,4,ZD,TO=ZD, /* Sum of Quantity */ X'40', /* Space */ 15,8,PD,TO=ZD) /* Sum of Amount */ /*
This example summarizes sales data by region and department. It sums up the quantity and amount fields, and creates a formatted summary record for each unique region/department combination.