A composite key is two or more fields concatenated into one contiguous block so that the sort (or a later step) can treat them as a single key. You might want to sort by region, then by date, then by id—you can do that with multiple sort keys in SORT FIELDS, or you can build one key that is region+date+id in that order at a known position (e.g. the start of the record) and sort by that one field. Building the composite in INREC is useful when key parts are scattered, need conversion (e.g. date to YYYYMMDD), or need padding so that character order matches the desired sort order. Because INREC runs before the sort, the sort sees the new record with the composite key at a fixed position. This page explains how to build composite keys with INREC BUILD (or FIELDS=), how to order and pad key parts, and when to use a composite key vs multiple SORT FIELDS keys.
You can sort by multiple keys by listing each key in SORT FIELDS=(pos1,len1,fmt1,dir1,pos2,len2,fmt2,dir2,...). Sometimes it is better to build one key that contains all key parts in order: (1) key parts may be in different places in the record and you want them in one block at the start; (2) key parts may need conversion (e.g. date to YYYYMMDD) or padding (e.g. leading zeros) so that a single character comparison gives the right order; (3) you want a simple SORT FIELDS=(1,keylen,CH,A) and possibly INCLUDE/OMIT on the same block. Building the composite in INREC creates a new record layout; the sort then runs on that layout, so the composite key drives the order.
In INREC BUILD= (or FIELDS=), you list items that make up the output record. Each item can be output_pos:input_start,length—copy length bytes from input at input_start to output starting at output_pos. To build a composite key, list the key parts in the order you want them, at consecutive output positions, usually starting at 1.
| Item | Meaning | Example |
|---|---|---|
| output_pos:input_start,len | Copy len bytes from input at input_start to output starting at output_pos | 1:10,5 → output 1–5 from input 10–14 |
| Constants | C'...' or X'...' insert literal bytes (e.g. padding, separator) | C'0' or spaces for alignment |
| Order in BUILD | Order of items = order of key parts in the composite | Region, then date, then id |
So to build key = region (bytes 10–14) then date (bytes 20–27) then id (bytes 1–5), you could use BUILD=(1:10,5,6:20,8,14:1,5,...). Output 1–5 = region, 6–13 = date, 14–18 = id; total key length 18. Then SORT FIELDS=(1,18,CH,A) sorts by that 18-byte composite. The rest of the BUILD list can copy the remaining input fields so the full record is available after the sort.
Input: region at 10–14 (5 bytes), date at 20–27 (8 bytes, YYYYMMDD), id at 1–5 (5 bytes). We want to sort by region, then date, then id. Build the composite at 1–18, then copy the rest of the record.
12INREC BUILD=(1:10,5,6:20,8,14:1,5,19:28,62) SORT FIELDS=(1,18,CH,A)
Output positions 1–5 = region, 6–13 = date, 14–18 = id (composite key 18 bytes). Positions 19–80 = input 28–80 (62 bytes). So the reformatted record is 80 bytes: key at 1–18, then the rest. SORT FIELDS=(1,18,CH,A) sorts by the entire composite. Character comparison of the 18 bytes gives region order, then date within region, then id within date—assuming the date is already in YYYYMMDD so that character order is chronological.
When you sort the composite as CH (character), DFSORT compares byte by byte. For numeric key parts to sort correctly, they must be padded so that character order matches numeric order. For example, 9 and 10: as two-byte character strings, "9" (followed by space) sorts after "10" because the first byte 9 > 1. So you need to right-justify with leading zeros: 009 and 010 so that 0 < 1 and 9 < 10. In INREC you can build such a field by copying a numeric field that is already stored with leading zeros, or by using conversion/editing (e.g. edit mask) to produce a fixed-width zero-padded value. If the key part is in PD or ZD and you want to avoid padding, you can instead use multiple sort keys (e.g. SORT FIELDS=(1,5,CH,A,6,4,PD,A)) so that the numeric part is compared as numeric, not character.
The composite key can include converted or edited fields. For example, if the input has a date in MMDDYYYY at 50–57, you can convert it to YYYYMMDD in INREC and place it in the key (e.g. with date conversion operands). Then the character order of the key is chronological. Similarly, you can include a field that was edited with an edit mask (e.g. for a display amount) if you want to sort by that formatted value. The BUILD list is built in order: any conversion or edit produces bytes at the specified output position, and those bytes become part of the composite key.
Multiple keys: SORT FIELDS=(10,5,CH,A,20,8,CH,A,1,5,CH,A) sorts by three separate fields. No INREC needed if the key fields are already in the right format and order does not require a single contiguous key. Composite key: Build key at 1–18 in INREC, then SORT FIELDS=(1,18,CH,A). Use a composite when (1) you want the key in one block (e.g. for INCLUDE on the key), (2) key parts need conversion or padding for CH sort, or (3) you prefer a single key specification. Both approaches give the same logical sort order when the key parts and formats are equivalent.
Putting the composite key at output position 1 is conventional: SORT FIELDS=(1,keylen,...) is simple, and INCLUDE/OMIT can reference the key with COND=(1,keylen,...). If you put the key elsewhere (e.g. 50–67), you must use that position in SORT FIELDS and in any conditions. So BUILD=(1:region_spec,2:date_spec,3:id_spec,...) with output positions 1, 2, 3, ... for each part keeps the key at the start.
Imagine you want to sort cards by color, then by number. One way is to tell the machine "first sort by color, then by number." Another way is to write a single label on each card that says "RED-005" or "BLUE-012"—color and number stuck together in order. Then the machine only has to sort by that one label. Building a composite key is like making that one label: we take the color and the number (and maybe more), put them in order, and write them at the top of the card. Then we sort by that one line. We do it before sorting (in INREC) so that when the sort looks at the card, it already sees the combined label.
1. Why build a composite key in INREC instead of using multiple keys in SORT FIELDS?
2. What is a composite sort key?
3. When building a composite key for character sort, why might you pad a numeric field?
4. Can you build a composite key in OUTREC?
5. In INREC BUILD=(1:50,5,6:20,8), what is the output layout?