In DFSORT, a summary record is either (1) a single record that represents a group of input records—for example one record per department with totals—or (2) a trailer line (or block) at the end of a report or after a section that shows counts and totals. You get the first kind with the SUM statement: after sorting by a key, SUM collapses each group into one record and fills specified numeric fields with sums (or other aggregates). You get the second kind with OUTFIL using TRAILER1 (grand total at end of report) and TRAILER3 (subtotal after each section when using SECTIONS=). This page explains both approaches and when to use each, including COUNT= and TOTAL= in trailers and IFTRAIL for updating an existing trailer record with actual counts and totals.
DFSORT gives you two main mechanisms for summary information:
Use SUM when you need a summarized dataset (e.g. one row per department with total sales). Use TRAILER1/TRAILER3 when you are building a report and want summary lines at the end or after each section.
SUM runs after the sort. The sort key defines the group: every record with the same value in the sort key belongs to the same group. SUM FIELDS= lists the numeric fields to sum (position, length, format for each). For each group, DFSORT adds those fields across all records in the group and writes one output record. The summed fields in that record contain the total; other fields (e.g. department code, name) typically come from the first record of the group. So you get a summary record per distinct key value.
Example: input has department (1,5), amount (10,6,PD). Sort by department and sum amount:
12SORT FIELDS=(1,5,CH,A) SUM FIELDS=(10,6,PD)
Output: one record per department. Position 1–5 is the department code (from the first record of the group), position 10–15 is the sum of the amount for that department. So the output dataset is a set of summary records.
If you use SUM FIELDS=NONE, you are not summing any numeric fields—you are just keeping one record per group (deduplication). That is still a form of summary: one representative record per key. So summary record generation via SUM can mean “one record per group with sums” or “one record per group (dedup only).”
TRAILER1 is the report trailer. It is written once, after all data records (and after any TRAILER3 lines for the last section). In TRAILER1 you typically put the grand total: total record count and/or sum of one or more numeric fields. Syntax is part of OUTFIL:
123OUTFIL FNAMES=OUTDD, TRAILER1=('TOTAL RECORDS: ',COUNT=(M11,LENGTH=7), ' TOTAL: ',TOTAL=(40,6,PD,LENGTH=12))
COUNT= inserts the number of data records. The format (e.g. M11) and LENGTH control how the number is edited (commas, width). TOTAL=(start,len,format,LENGTH=outlen) sums the numeric field at the given start position and length, in the given format (PD packed decimal, ZD zoned decimal, BI binary), and writes the result in the trailer formatted to outlen characters. So you get one summary line at the end with “TOTAL RECORDS: nnnnnnn TOTAL: xxxxxxxxxxxx”.
TRAILER1 can contain literals, multiple COUNT= and TOTAL= items, and fixed positions. It does not change the data records; it appends one or more trailer lines (or a trailer block) to the report.
When you use SECTIONS= you define control-break groups (e.g. by department). After the last data record of each section, DFSORT can write a TRAILER3 line. So you get a subtotal after each group—count and/or total for that section only. TRAILER3 is specified inside the SECTIONS= parameter:
123456OUTFIL FNAMES=OUTDD, SECTIONS=(1,5,SKIP=2L, TRAILER3=(1:'Dept ',1,5,' Count: ',COUNT=(M11,LENGTH=6), ' Total: ',TOTAL=(10,6,PD,LENGTH=12))), TRAILER1=(1:'GRAND TOTAL ',COUNT=(M11,LENGTH=10), ' ',TOTAL=(10,6,PD,LENGTH=14))
Here the section key is bytes 1–5 (e.g. department). After each department, TRAILER3 prints a line with the department code (1,5), the count of records in that section, and the sum of the 6-byte PD field at position 10. At the very end, TRAILER1 prints the grand total count and sum. So summary record generation for sections is done with TRAILER3; the grand summary is TRAILER1.
In both TRAILER1 and TRAILER3 you use the same building blocks:
| Item | Meaning |
|---|---|
| COUNT=(format,LENGTH=n) | Inserts the number of records in the current scope. In TRAILER1, scope is all data records; in TRAILER3, scope is the current section. Format (e.g. M11) and LENGTH control editing and width. |
| TOTAL=(start,len,format,LENGTH=n) | Sums the numeric field at start position and length, in the given format (PD, ZD, BI). Writes the sum in the trailer, formatted to n characters. Scope is the same as COUNT (all records in TRAILER1, section only in TRAILER3). |
| Literals and field refs | You can mix fixed text (e.g. 'Dept ') and field positions (e.g. 1,5 to print the section key) so the trailer line is readable (e.g. "Dept SALES Count: 25 Total: 15000"). |
The format in TOTAL= must match the data: PD for packed decimal, ZD for zoned decimal, BI for binary. Wrong format can cause incorrect totals or abends. The start and length refer to the position in the input (or INREC) record.
Sometimes the input file already has a trailer record—for example a fixed-format line with “T” in column 1 and reserved positions for “record count” and “total amount.” You do not want to append a new line; you want to update that existing record with the actual count and total. That is what IFTRAIL does.
You identify the trailer record with TRLID= using a logical expression (e.g. position 1, length 1, character, equal to 'T'). You specify what to update with TRLUPD=: at which positions to put COUNT= and/or TOT= (or TOTAL=). If the first record of the file is a header that should not be counted or summed, use HD=YES. DFSORT then updates the identified trailer record in place and writes it to the output; the rest of the file is processed as usual.
1234OUTFIL FNAMES=OUTDD, IFTRAIL=(HD=YES, TRLID=(1,1,CH,EQ,C'T'), TRLUPD=(21:COUNT=(M11,LENGTH=7),35:TOTAL=(40,6,PD,LENGTH=12)))
Here the trailer is the record with 'T' in position 1. TRLUPD updates position 21 with the record count (7 characters) and position 35 with the sum of the 6-byte PD field at 40, formatted to 12 characters. So the output file has the same trailer record layout, but with real values filled in—another form of summary record generation.
Use SUM when your goal is a summarized dataset: one record per key with totals in specified fields, to be used as input to another step or as a final extract. Use TRAILER1/TRAILER3 when your goal is a report with summary lines at the end or after each section. Use IFTRAIL when the output file must preserve an existing trailer layout and you only need to fill in the count and total values.
Imagine you have a list of lemonade sales: each line says which stand and how much they sold. A summary record could be: one line per stand that says “Stand A total: $50.” That’s like SUM—squish all the lines for the same stand into one line with the total. Or the summary could be an extra line at the bottom of the list: “TOTAL STANDS: 3 TOTAL MONEY: $120.” That’s like TRAILER1—one line at the end with the big totals. And if your list already had a line at the bottom that said “TOTAL: …….” with empty spaces, and you want to fill in those spaces with the real numbers, that’s like IFTRAIL—update the line that’s already there.
1. What does SUM FIELDS= produce when you sort by a key and sum numeric fields?
2. Where do you put a grand total (e.g. total record count or sum of a numeric field) at the end of an OUTFIL report?
3. What is the difference between TRAILER1 and TRAILER3 when generating summary information?
4. What is IFTRAIL used for in OUTFIL?
5. When using SUM FIELDS=, what defines the "group" for each summary record?