DFSORT lets you sort by more than one key. You specify a primary key (first in the list), a secondary key (second), and optionally a tertiary or more keys. Records are ordered by the primary key first; when two records have the same value in the primary key, the secondary key is used to decide which comes first; when they are also equal on the secondary key, the third key is used; and so on. Each key has its own position, length, format, and direction (A or D), so you can mix character and numeric keys and mix ascending and descending. This page explains how multiple keys work, how tie-breaking order is determined, and how to code and think about primary, secondary, and tertiary keys.
A single sort key is enough when every record has a unique value in that key (e.g. unique ID). Often, though, many records share the same value in the primary field—for example, many transactions for the same customer, or many lines with the same department code. If you sort only by customer or only by department, the order of records within that group is arbitrary (or depends on input order). To get a consistent, useful order within each group, you add a second key. For example: sort by customer (primary) so all of customer A are together, then by date (secondary) so within customer A the earliest date is first. You can add a third key to break ties further (e.g. by amount within the same customer and date). Multiple keys give you a well-defined order for the whole file.
DFSORT compares records using the keys in the order you list them. The primary key is the first 4-tuple. When comparing two records, DFSORT first compares the primary key. If one record has a smaller (or larger, for descending) value in the primary key, that record is ordered first—the secondary key is not looked at. Only when the primary key values are equal does DFSORT use the secondary key to decide order. If the secondary key is also equal, it uses the tertiary key, and so on. So the primary key has the highest priority; the secondary is only for tie-breaking when the primary is equal; the tertiary is only for tie-breaking when both primary and secondary are equal. This is exactly like sorting a spreadsheet by "Column A, then Column B, then Column C."
For each key you specify four values: position, length, format, and direction. So for two keys you have eight values: (pos1, len1, fmt1, dir1, pos2, len2, fmt2, dir2). For three keys you have twelve values. There is no comma or keyword between keys—just the next 4-tuple. Example:
1SORT FIELDS=(1,20,CH,A,21,4,PD,D,25,8,ZD,A)
Primary: bytes 1–20, character, ascending. Secondary: bytes 21–24, packed decimal, descending. Tertiary: bytes 25–32, zoned decimal, ascending. So records are ordered by name (1–20) A–Z; within the same name, by amount (21–24) high to low; within the same name and amount, by the third field (25–32) low to high.
The primary key can be character (CH) and the secondary numeric (PD or ZD). The primary can be ascending (A) and the secondary descending (D). There is no requirement that keys share format or direction. You choose each key's format based on how that field is stored in the record, and each key's direction based on whether you want low-to-high or high-to-low for that field. So multiple keys are very flexible: you can sort by name A–Z, then by amount largest first, then by date oldest first, all in one SORT FIELDS=.
When two records are equal on all specified keys, their relative order in the output may depend on whether DFSORT uses a stable sort. A stable sort preserves the relative order of equal elements from the input. So if record X came before record Y in the input and they are equal on all keys, X will still come before Y in the output. If the sort is not stable, the order of equal records is undefined. OPTION EQUALS (or similar) can affect this; see your product documentation. For most purposes, once you have enough keys to break ties where it matters, you do not need to rely on input order.
Suppose each record has: customer ID bytes 1–10, transaction date bytes 11–18 (YYYYMMDD), amount bytes 19–22 (packed). You want the report in customer order (A–Z), and within each customer by date (oldest first), and within the same customer and date by amount (largest first). You would code:
1SORT FIELDS=(1,10,CH,A,11,8,CH,A,19,4,PD,D)
Primary: customer ID (1–10) ascending. Secondary: date (11–18) ascending—use CH if stored as character digits (YYYYMMDD sorts correctly as character). Tertiary: amount (19–22) descending. So you get one block per customer, chronological within customer, and within the same day the highest amount first.
DFSORT supports a large number of keys (dozens or more in typical products). The limit is product- and release-specific. For most applications, two to five keys are enough. If you need many more, check your DFSORT documentation for the maximum number of sort control fields.
Multiple sort keys are like lining up by "first by color, then by size." Everyone with red goes first, then blue, then green (that's the first key). Within the red group, you line up by size: smallest red first, then bigger red (that's the second key). So the first key puts people into big groups, and the second key orders them within each group. If two people have the same color and same size, you might use a third rule (third key) or just leave them in the order they were.
1. How does DFSORT use the second sort key?
2. How do you specify a third sort key in SORT FIELDS?
3. Can the primary key be character and the secondary be numeric?
4. What is the "primary" sort key?
5. If two records are equal on both the first and second key, what happens?