Window processing in DFSORT means processing records in a "window"—either a group of consecutive records that share a key (e.g. all records for the same account) or using context from the previous record (e.g. carrying a value forward). DFSORT does not have a built-in "sliding window" that can look at the next record in one pass. It does support group-based windows with OUTFIL SECTIONS= and INREC/OUTREC WHEN=GROUP, and "carry forward" from the current record to subsequent records in the group with PUSH. For true next-record logic or N-record sliding windows (e.g. moving average), you typically use a user exit or a COBOL program that reads the sorted file and maintains a small buffer. This tutorial explains what window processing means and how to do it with DFSORT.
A "window" is a set of records you consider together. In batch processing, two common kinds are: (1) a group window—all consecutive records with the same key (e.g. same account ID); (2) a sliding window—a fixed number of consecutive records (e.g. "the previous 5 records") or "current record plus next record." DFSORT supports group windows well with SECTIONS= and WHEN=GROUP. It supports "previous record" context by carrying data forward with PUSH. It does not support "next record" or arbitrary N-record sliding windows in control statements; for that you need an exit or a program.
To treat "all records with the same key" as a window, sort by that key first. Then you can use OUTFIL SECTIONS=(position,length,format) so that each distinct key value is one section. Within that section you can print HEADER and TRAILER; you are not changing record content, but you are defining the window. Alternatively, use INREC or OUTREC with WHEN=GROUP and KEYBEGIN=(position,length) KEYEND=(position,length) to define the same group. With WHEN=GROUP you can use BUILD, OVERLAY, and PUSH to change records based on their position in the group—for example, only the first record gets a certain value, and PUSH can copy that value to the rest of the group. So WHEN=GROUP gives you a window (the group) and the ability to propagate data within it.
PUSH is used with WHEN=GROUP. It copies data from the current record (where the WHEN condition is true) into the same positions in subsequent records of the group. Syntax is PUSH=(output_start:input_start,length) or multiple PUSH specifications. For example, the first record in each group might have a "header" value in 1–20; PUSH=(1:1,20) would copy that 20-byte value into positions 1–20 of every following record in the group until the key changes. So later records in the group "see" the previous (first) record's value—that is window-like context. PUSH requires z/OS DFSORT with support for WHEN=GROUP (e.g. PTF UK90013 or later). It is the main way to get "previous record" effect without a user exit.
Input: some records have account ID in 1–10; others (detail records) have blanks in 1–10 and follow the account header. You want to fill 1–10 in every detail record with the account ID from the preceding header. Sort by a key that keeps header and its details together; use WHEN=GROUP; in the first record of the group (e.g. when 1–10 is not blank) BUILD the record and PUSH=(1:1,10) so 1–10 is copied to following records.
1234INREC IFTHEN=(WHEN=GROUP, KEYBEGIN=(1,10), KEYEND=(1,10), PUSH=(1:1,10))
KEYBEGIN and KEYEND define the group key (here 1–10). When the key changes, a new group starts. PUSH=(1:1,10) copies positions 1–10 from the record where the condition is applied (e.g. the first record of the group, which has the account ID) into positions 1–10 of subsequent records in the group. So every record in the group gets the account ID from the "header" record. That is window processing: the window is the group, and the first record's value is carried forward.
DFSORT reads input sequentially and writes output sequentially. Control statements do not have a variable that means "the next record." So you cannot say "if the next record has key X then omit this record" or "output the sum of current and next amount" in one pass. To implement next-record logic, you need either a user exit (E15 for input, E35 for output) that buffers one record and can look ahead, or a separate program that reads the sorted file and maintains a one-record (or N-record) lookahead buffer. Many shops use a small COBOL program for "compare current with next" or "moving average over last N records" because it is easier to read and maintain than exit code.
Use a COBOL (or other) program when: you need to compare the current record with the next; you need a true sliding window of N records (e.g. moving average); or the window logic is complex and would require multiple passes or exits. The program reads the sorted input and can keep a buffer of records, so it has full "window" context. Use DFSORT when: the window is simply "all records with the same key" and you only need to carry forward a value (PUSH) or print headers/trailers (SECTIONS). DFSORT is optimized for sort and group-level operations; programs are better for arbitrary per-record logic with lookahead.
| Goal | Approach |
|---|---|
| Group of records (same key) as window | Sort by key. Use OUTFIL SECTIONS=(key) or INREC/OUTREC WHEN=GROUP KEYBEGIN/KEYEND. |
| Carry forward value from previous record | WHEN=GROUP with PUSH=(out:in,len) to copy from current record to following records in group. |
| Next-record or N-record sliding window | Use a user exit (E15/E35) with buffer or a COBOL program that reads sorted input with lookahead. |
Imagine a line of kids: first one with a red hat, then several without hats. A "window" can mean "all the kids in one family" (a group). DFSORT can say: "Copy the red hat from the first kid to all the next kids in the same family." That's PUSH—everyone in the group gets the same value from the first. But DFSORT cannot look at the next kid in line and say "if the next kid has a blue hat, do something different." For that you need a helper (a program) who can peek at the next kid. So DFSORT is great for "same family" windows and copying the first value to the rest; for "what's coming next" you need another tool.
1. What is "window processing" in the context of DFSORT?
2. What is the PUSH parameter used for in DFSORT?
3. How do you define a "window" as a group of consecutive records with the same key?
4. Can DFSORT look at the "next" record in one pass?
5. When would you use a COBOL program instead of DFSORT for window logic?