MainframeMaster

Group-Based Numbering

Group-based numbering in DFSORT means assigning sequence numbers that restart for each group—e.g. 1, 2, 3 for the first group (e.g. first department), then 1, 2, 3 again for the next group. That is the same idea as resetting sequence numbers at control breaks. You can achieve it in two main ways: RESTART=(position,length) on SEQNUM (groups are "same value in this control field") and WHEN=GROUP with SEQ=n (groups are defined by BEGIN=, END=, or RECORDS=n). This page compares both approaches, explains when to use key-based vs expression-based or fixed-size groups, and shows how to combine group-based numbering with sorting and conditional sequencing.

Sequence Numbers
Progress0 of 0 lessons

Two Ways to Define Groups

For per-group numbering you need two things: (1) a way to define what a "group" is, and (2) a way to reset the sequence when a new group starts. DFSORT offers:

RESTART= vs WHEN=GROUP
MethodHow the group is definedTypical use
RESTART=(pos,len)Group = consecutive records with the same value in the control field. Reset when the value changes.Control break by key (department, order id, etc.). File must be sorted by that field.
WHEN=GROUP SEQ=nGroup defined by BEGIN=(logexp), END=(logexp), or RECORDS=n. BEGIN= marks start of new group; RECORDS=n = every n records.Expression-based (e.g. when byte 1 = "A") or fixed-size blocks (e.g. every 100 records).

Use RESTART= when your groups are naturally "all records with the same value in this field"—e.g. same order id, same department. Sort by that field first so the groups are contiguous. Use WHEN=GROUP when groups are defined by a condition (BEGIN=/END=) or by a fixed record count (RECORDS=n).

RESTART=: Key-Based Groups

With SEQNUM you specify RESTART=(position,length). position and length identify a control field in the record. As DFSORT processes records in order, it compares this field to the previous record. When the value changes, the sequence number is reset to the starting value (1 or START=). So the first record of each new value gets 1, the second gets 2, and so on.

For this to match your idea of "one group per order" or "one group per department," the file must be sorted by that control field. Then all records with the same value are adjacent, and you get one run of 1, 2, 3, … per group.

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

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

WHEN=GROUP: Expression-Based or Fixed-Size Groups

IFTHEN with WHEN=GROUP lets you define groups in other ways. You can use BEGIN=(logexp) to mark the start of a new group when a logical expression is true (e.g. when a control field equals a value). You can use RECORDS=n so that every n records form a new group—useful for fixed-size blocks. SEQ=n adds a zoned decimal sequence number of length n that starts at 1 for each group and increments by 1 within the group.

WHEN=GROUP is processed early (like WHEN=INIT), before WHEN=(logexp). So the group sequence is on the record before other conditional overlays. See the WHEN=GROUP tutorial for full syntax (PUSH=, BEGIN=, END=, RECORDS=).

text
1
2
3
OPTION COPY OUTREC IFTHEN=(WHEN=GROUP,BEGIN=(1,5,CH,EQ,C'START'),RECORDS=9999, PUSH=(21:SEQ=5))

Here a new group starts when bytes 1–5 equal "START". SEQ=5 adds a 5-byte sequence number (PUSH= places it at 21) that restarts at 1 for each such group. So you get 1, 2, 3, … within each block of records that begins with "START".

Fixed-Size Groups: RECORDS=n

When each group is exactly n records (e.g. every 10 records, or every 100), use WHEN=GROUP with RECORDS=n. The first n records get 1, 2, …, n; the next n records get 1, 2, …, n again; and so on. There is no need for a control field or sort order—the group boundary is purely by count.

RESTART= cannot do this because it depends on a field value change. So for fixed-size groups, WHEN=GROUP with RECORDS=n is the right tool.

START= and INCR= with Group Numbering

Both RESTART= and WHEN=GROUP (with SEQ=) work with START= and INCR= where supported. START= sets the value used when the sequence starts or restarts (e.g. each new group begins at 100). INCR= sets the step (e.g. 10 for 100, 110, 120, …). So you can have per-group numbering that starts at 100 and increments by 10 within each group.

Choosing RESTART= vs WHEN=GROUP

  • Groups = same value in a field (e.g. order id, department): Sort by that field and use RESTART=(position,length). Simple and direct.
  • Groups = fixed number of records (e.g. every 50 records): Use WHEN=GROUP with RECORDS=50 and SEQ=n.
  • Groups = when a condition is true (e.g. when byte 1 = "A"): Use WHEN=GROUP with BEGIN=(logexp) and SEQ=n.

Combining with Conditional Sequencing

You can combine group-based numbering with conditional sequencing. For example, only detail records get a per-group sequence number; header and trailer records get blanks. Use IFTHEN: in the WHEN clause for detail records use OVERLAY with SEQNUM and RESTART= (or use WHEN=GROUP in a way that only applies to details). In WHEN=NONE overlay the sequence field with blanks. Then you get 1, 2, 3 within each group only on the lines you want numbered.

Explain It Like I'm Five

Imagine numbering the kids in each class. You don't want one long list 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" can be the value in a field (RESTART=) or a rule like "every 10 kids" (RECORDS=10). You line up by class first when using RESTART=, then number 1, 2, 3 in each class. That's group-based numbering.

Exercises

  1. Your file is sorted by bytes 20–25 (customer id). You want a 4-byte sequence at position 26 that is 1, 2, 3, … within each customer. Write the OUTREC with RESTART=.
  2. You want every 20 records to form a group, with sequence 1–20 in each group. Which method do you use (RESTART= or WHEN=GROUP) and why?
  3. When would you use WHEN=GROUP BEGIN= instead of RESTART= for per-group numbering?

Quiz

Test Your Knowledge

1. What is the main difference between RESTART= and WHEN=GROUP SEQ= for per-group numbering?

  • RESTART= is only in INREC
  • RESTART= resets when a control field value changes (key-based); WHEN=GROUP defines groups with BEGIN=/END=/RECORDS= (expression or count based)
  • WHEN=GROUP cannot use SEQ=
  • They are the same

2. When would you use RECORDS=n in WHEN=GROUP?

  • To sort n records
  • To define a group as "every n records"—e.g. every 10 records start a new group, so you get 1–10 in group 1, 1–10 in group 2
  • Only for the first group
  • To skip n records

3. For "line 1, 2, 3 within each department" when department is in bytes 1–5 and the file is sorted by department, which is simpler?

  • WHEN=GROUP with BEGIN= and END=
  • SEQNUM with RESTART=(1,5)—sort by 1–5, then OUTREC OVERLAY with SEQNUM,RESTART=(1,5)
  • Conditional sequencing only
  • INCLUDE only

4. Can you combine group-based numbering with conditional sequencing?

  • No
  • Yes—e.g. only detail records get a per-group sequence number (IFTHEN WHEN=detail with SEQNUM,RESTART=), while headers get blanks
  • Only in INREC
  • Only with RECORDS=

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

  • DFSORT requires it for all OUTREC
  • So that all records with the same control field value are adjacent—otherwise the sequence would reset every time the value changes, possibly in the middle of what you consider one group
  • Only for WHEN=GROUP
  • It is not required