MainframeMaster

Conditional Sequencing

Conditional sequencing in DFSORT means assigning sequence numbers only when a condition is true. For example, you might want line numbers 1, 2, 3, … only on detail records in a report, while header and trailer records show blanks or a fixed label in the sequence field. Or you might want different START= or INCR= values for different record types (e.g. type A numbered from 100, type B from 1000). You achieve this by combining SEQNUM with IFTHEN in OUTREC or INREC: the WHEN clause that matches the records you want numbered contains SEQNUM; other WHEN clauses overlay the sequence field with spaces or a constant so those records do not get a number. This page explains how to apply SEQNUM conditionally, how the counter behaves when some records are skipped, and when to use INREC vs OUTREC.

Sequence Numbers
Progress0 of 0 lessons

Why Conditional Sequencing?

A single running sequence (1, 2, 3, … for every record) is what you get with a plain SEQNUM in OUTREC or INREC. In reports you often need:

  • Only detail lines numbered; headers and trailers should show blanks or a label so the printed "line number" column does not count titles or footers.
  • Different number ranges by record type—e.g. order lines 1–999 and shipment lines 1000–1999.
  • Skip certain records (e.g. comment lines) so the sequence reflects only "real" data lines.

Conditional sequencing uses IFTHEN to apply SEQNUM only in the WHEN clause(s) where you want a number; in other WHEN clauses you overlay the same output position with blanks or a constant so that the counter is not "used" for those records (or you use a separate counter per type).

Basic Pattern: SEQNUM Only for Matching Records

Suppose the record type is in byte 1: H = header, D = detail, T = trailer. You want a 5-byte sequence number at position 21 only for detail records; headers and trailers should have blanks at 21–25. Sort first, then in OUTREC use IFTHEN so that only when byte 1 is "D" do you put SEQNUM there; otherwise overlay 21–25 with spaces.

text
1
2
3
4
5
SORT FIELDS=(2,10,CH,A) OUTREC IFTHEN=(WHEN=INIT,BUILD=(1:1,80)), IFTHEN=(WHEN=(1,1,CH,EQ,C'D'), OVERLAY=(21:SEQNUM,5,ZD)), IFTHEN=(WHEN=NONE,OVERLAY=(21:5C' '))

WHEN=INIT copies the full record (1–80). The second IFTHEN applies when byte 1 equals D: it overlays positions 21–25 with SEQNUM,5,ZD. The third IFTHEN, WHEN=NONE, catches any record that did not match the previous WHEN (i.e. H and T): it overlays 21–25 with five spaces. So only detail records get a number; the sequence counter increments only for those records. The first detail gets 1, the second gets 2, and a header or trailer in between does not get a number and does not advance the counter.

How the Counter Behaves

When SEQNUM appears inside a WHEN clause, only records that satisfy that WHEN receive a value from the counter and advance it. Records that hit WHEN=NONE or another WHEN that does not contain SEQNUM do not advance the counter. So you get one running sequence for all records that actually get SEQNUM—ideal for "number only the detail lines" in report order.

Counter behavior with conditional SEQNUM
RecordWHEN matchedEffect on sequence field and counter
Header (H)WHEN=NONEOverlay blanks; counter unchanged.
Detail 1 (D)WHEN=(1,1,CH,EQ,C'D')Gets 1; counter advances to 2.
Detail 2 (D)WHEN=(1,1,CH,EQ,C'D')Gets 2; counter advances to 3.
Trailer (T)WHEN=NONEOverlay blanks; counter unchanged (still 3).
Detail 3 (D)WHEN=(1,1,CH,EQ,C'D')Gets 3; counter advances to 4.

Multiple Record Types with Different Ranges

If you want type A records numbered 100, 101, 102, … and type B records numbered 1000, 1001, 1002, …, use separate IFTHEN clauses. Each WHEN that contains its own SEQNUM maintains a separate counter. So one clause can have SEQNUM,5,ZD,START=100 and another SEQNUM,5,ZD,START=1000. Each applies only to its record type and increments independently.

text
1
2
3
4
OUTREC IFTHEN=(WHEN=INIT,BUILD=(1:1,80)), IFTHEN=(WHEN=(1,1,CH,EQ,C'A'),OVERLAY=(21:SEQNUM,5,ZD,START=100)), IFTHEN=(WHEN=(1,1,CH,EQ,C'B'),OVERLAY=(21:SEQNUM,5,ZD,START=1000)), IFTHEN=(WHEN=NONE,OVERLAY=(21:5C' '))

Type A records get 100, 101, 102, … in the order they appear. Type B records get 1000, 1001, 1002, … in the order they appear. Headers or other types (WHEN=NONE) get blanks. The two sequences are independent.

INREC vs OUTREC for Conditional Sequencing

Use OUTREC when you want the sequence to reflect final output order—e.g. report line numbers only on detail lines after the sort. Use INREC when you need conditional numbering before the sort or filter: for example, only detail records get a sequence number in input order, and you later SORT by that number (and other keys) to restore or preserve order. For most "report with line numbers only on details," OUTREC with IFTHEN is the right choice.

INREC vs OUTREC for conditional SEQNUM
PhaseUse when
OUTRECSequence should reflect sorted/output order; e.g. line numbers only on detail lines in the report.
INRECNumbering must be in input order or must be visible to INCLUDE/OMIT or SORT (e.g. preserve original order within a group).

Combining with RESTART=

You can combine conditional SEQNUM with RESTART=. For example, only detail records get a sequence number, and that number resets when a control field (e.g. order id) changes. Use RESTART= in the same WHEN clause that contains SEQNUM: e.g. OVERLAY=(21:SEQNUM,5,ZD,RESTART=(2,10)) inside the WHEN for detail records. Then only details are numbered, and the sequence resets at each new value of bytes 2–11 (e.g. order id). The file must be sorted by that control field so groups are contiguous.

Order of WHEN Clauses

IFTHEN is evaluated in order. Typically you use WHEN=INIT first to establish the base record, then one or more WHEN=(condition) clauses for record types that get SEQNUM, and finally WHEN=NONE to handle any remaining records (e.g. headers/trailers) with blanks or a constant. Ensure the condition for "numbered" records is specific enough that only the intended records get SEQNUM; WHEN=NONE catches everything that did not match a previous WHEN.

Explain It Like I'm Five

Imagine numbering only the apples in a row that has apples, labels, and a "end of box" card. You do not want to put a number on the label or the end card—only on the apples. So you have a rule: "If it's an apple, give it the next number (1, 2, 3…). If it's not an apple, leave the number spot blank." Conditional sequencing is the same: only the records that match your "detail" rule get a number; the rest get a blank or a label so the printed list shows numbers only where you want them.

Exercises

  1. Your file has byte 1 = "H", "D", or "T". You want positions 1–80 as-is and a 5-byte sequence at 81 only for "D" records. Write the OUTREC IFTHEN (assume BUILD or OVERLAY for 1–80 as needed).
  2. If you use two WHEN clauses each with SEQNUM,START= different values, do they share one counter or two? What does that mean for the output?
  3. You want detail records numbered 1, 2, 3, … within each order (order id in bytes 1–10), and headers/trailers unnumbered. What do you need in addition to RESTART=(1,10)?

Quiz

Test Your Knowledge

1. You want sequence numbers only on detail records (byte 1 = "D"), not on header or trailer records. How do you do it?

  • Use INCLUDE to keep only detail records, then add SEQNUM
  • Use OUTREC IFTHEN: WHEN=(1,1,CH,EQ,C'D') add SEQNUM; WHEN=NONE or other WHEN clauses leave the sequence field blank or constant
  • Use RESTART= only
  • SEQNUM cannot be conditional

2. If you use IFTHEN WHEN=(1,1,CH,EQ,C'D') with SEQNUM for details and WHEN=NONE with OVERLAY=(21:20C' ') for others, what happens to the sequence counter for header records?

  • The counter resets
  • The counter still increments but the header does not show it; the next detail gets the next number
  • Headers get 0
  • Invalid syntax

3. Where should you add conditional SEQNUM when you need final report order line numbers only on detail lines?

  • INREC only
  • OUTREC—after sort, so the sequence reflects the order records are written; use IFTHEN to apply SEQNUM only to detail records
  • INCLUDE only
  • In a second sort step

4. Can you use different START= or INCR= for different record types in one DFSORT step?

  • No; START= and INCR= are global
  • Yes; use separate IFTHEN clauses, each with its own SEQNUM,START=,INCR= in OVERLAY or BUILD—each SEQNUM in a WHEN maintains its own counter
  • Only in INREC
  • Only with RESTART=

5. What is a typical use for conditional sequencing?

  • Sorting only
  • Numbering only detail or data lines in a report while leaving headers/trailers with blanks or labels; or numbering different record types with different ranges
  • De-duplication only
  • Merge only