MainframeMaster

Resetting Sequence Numbers

Resetting sequence numbers in DFSORT means making the sequence start over (e.g. back to 1 or to START=) at certain points—typically at each group or control break. For example, you want line numbers 1, 2, 3 within each order, and then 1, 2, 3 again for the next order. You can do this with RESTART=(position,length) on SEQNUM: when the value in the specified control field changes from one record to the next, the sequence resets. The file should be sorted by that control field so that all records in the same group are contiguous. Alternatively you can use WHEN=GROUP with SEQ=n in IFTHEN, defining groups with BEGIN=, END=, or RECORDS=. This page explains RESTART=, why sort order matters, WHEN=GROUP SEQ=, and how to choose between them.

Sequence Numbers
Progress0 of 0 lessons

Why Reset the Sequence?

A single running sequence (1, 2, 3, … for the whole file) is enough for report line numbers or global position. Often you need per-group numbering: 1, 2, 3 for the first group (e.g. first order), then 1, 2, 3 again for the second group (second order). That is a control break: the sequence resets whenever a controlling field (e.g. order id, department, region) changes. DFSORT supports this with RESTART= on SEQNUM and with WHEN=GROUP and SEQ=n in IFTHEN.

RESTART=(position,length)

With SEQNUM you can add RESTART=(position,length). position and length define a control field in the record. When DFSORT moves from one record to the next, it compares the value of this field. If the value changes, the sequence number is reset to the starting value (1 or START=). So the first record of each new "group" (each new value of the control field) gets 1 (or START=), the second gets 2 (or START+INCR), and so on.

For this to match your idea of "group," the file must be ordered by that control field. So you sort by the same (position, length) (or by a key that includes it) first. Then all records with the same value are adjacent, and the sequence runs 1, 2, 3, … for that block and resets when the value changes.

text
1
2
SORT FIELDS=(1,10,CH,A) OUTREC OVERLAY=(11:SEQNUM,5,ZD,RESTART=(1,10))

Records are sorted by the first 10 bytes (e.g. order id). OUTREC overlays position 11 with a 5-byte ZD sequence number. RESTART=(1,10) means: when the value in bytes 1–10 changes, reset the sequence. So within each order id you get 1, 2, 3, … and the next order id starts again at 1.

Sort Order and Control Field

RESTART= resets the sequence whenever the control field value changes from one record to the next. So the "groups" are simply runs of records with the same value. If the file is not sorted by that field, the same value can appear in many places—and the sequence would reset every time it appears. So you would get many short runs of 1, 2, 1, 2, 1 instead of one long run of 1, 2, 3, 4, 5 per group. Always sort by the control field (or by a key that includes it) so that each distinct value forms one contiguous block.

RESTART= and sort order
Sort by control field?Effect
YesEach distinct value forms one block. Sequence runs 1,2,3,… per block and resets at each new value. Correct per-group numbering.
NoSame value can appear in scattered records. Sequence resets every time the value changes, often in the middle of a logical group. Usually wrong.

START= and INCR= with RESTART=

START= sets the value used when the sequence starts and when it restarts. So with RESTART=, every new group gets START= (or 1 if START= is omitted) as its first number. INCR= still defines the step within each group. Example: SEQNUM,5,ZD,START=100,INCR=10,RESTART=(1,8) gives 100, 110, 120, … for the first group; when the control field changes, the next group gets 100, 110, 120, … again.

WHEN=GROUP and SEQ=n

Another way to get per-group sequence numbers is IFTHEN with WHEN=GROUP. You define groups using BEGIN=, END=, or RECORDS=, and use SEQ=n to add a sequence number of length n (zoned decimal) that starts at 1 for the first record of each group and increments by 1 within the group. WHEN=GROUP is processed early, like WHEN=INIT, before WHEN=(logexp). So you get group-based numbering with a logical (expression-based) group definition rather than a simple "when this field changes" rule. See the WHEN=GROUP tutorial for full syntax (PUSH=, BEGIN=, END=, RECORDS=).

RESTART= is simpler when your groups are exactly "same value in this field": sort by that field and use RESTART=(position,length). WHEN=GROUP is useful when groups are defined by a condition (e.g. BEGIN=(1,2,CH,EQ,C'01') and END=(1,2,CH,EQ,C'99')) or by a fixed number of records per group (RECORDS=).

INREC vs OUTREC with RESTART=

You can use RESTART= with SEQNUM in both INREC and OUTREC. In INREC, the control field is the one in the INREC record (after INREC is applied). The sequence is assigned in input order, but it still resets when that control field changes. So if the input is already ordered by the control field, INREC SEQNUM,RESTART= gives per-group numbers in input order. In OUTREC, the control field is the record as it is at output time (after sort). So you sort by the control field, then OUTREC assigns the sequence in output order and resets when the control field changes. For report-style output (sorted, then numbered within each group), OUTREC with RESTART= is the usual choice.

Example: Line Numbers Within Each Department

Suppose records have department in bytes 1–5 and you want a 5-byte line number at position 6 that is 1, 2, 3, … within each department. Sort by department, then overlay the sequence number with RESTART= on the department field:

text
1
2
SORT FIELDS=(1,5,CH,A) OUTREC OVERLAY=(6:SEQNUM,5,ZD,RESTART=(1,5))

After the sort, all records for department A are together, then department B, and so on. OUTREC assigns 1, 2, 3, … for department A; when bytes 1–5 change to department B, the sequence resets to 1, 2, 3, … for B; and so on.

Explain It Like I'm Five

Imagine numbering the kids in each class. You don't want one long list (1, 2, 3, … for the whole school). You want: in Class A, number them 1, 2, 3; in Class B, number them 1, 2, 3 again. So you "reset" the counter every time you move to a new class. In DFSORT, the "class" is the control field (e.g. department or order id). You line up everyone by class first (sort), then you number them 1, 2, 3 in each class and start over at 1 when the class name changes. That's RESTART=.

Exercises

  1. You have a file sorted by bytes 1–8 (customer id). You want a 4-byte sequence number at position 9 that is 1, 2, 3, … within each customer. Write the OUTREC with RESTART=.
  2. What goes wrong if you use RESTART=(1,8) but the file is sorted by bytes 20–25 instead of 1–8?
  3. When would you use WHEN=GROUP SEQ=n instead of RESTART= for per-group numbering?

Quiz

Test Your Knowledge

1. What does RESTART=(position,length) do with SEQNUM?

  • Restarts the DFSORT job
  • Resets the sequence number (e.g. to 1 or START=) when the value in the specified control field changes from one record to the next
  • Restarts the sort
  • Length of the record

2. Why must the file be sorted by the RESTART= control field?

  • DFSORT requires it
  • So that all records in the same group are together; otherwise the sequence would reset every time the field changes, which could be in the middle of a logical group
  • Only for OUTREC
  • It is not required

3. What is WHEN=GROUP SEQ=n used for?

  • To filter records
  • To add a sequence number that restarts at 1 for the first record of each group (control-break style); groups are defined by BEGIN=, END=, or RECORDS=
  • To sort by group
  • Only in INCLUDE

4. If you use RESTART=(1,10) and the file is sorted by bytes 1–10, what happens at each new value of bytes 1–10?

  • The sort restarts
  • The sequence number resets (e.g. to 1); so the first record with that value gets 1, the next gets 2, and so on until bytes 1–10 change again
  • Nothing
  • Only the first group gets numbers

5. Can you use both START= and RESTART= with SEQNUM?

  • No
  • Yes; START= sets the value used when the sequence starts or restarts; RESTART= defines when it restarts (when the control field changes)
  • Only in INREC
  • Only when INCR=10