3.3 Match-Merging with BY Statements & FIRST./LAST. Processing
Key Takeaways
- Match-merging uses a MERGE statement accompanied by a BY statement to join observations horizontally based on common key values across pre-sorted input datasets.
- During BY-group processing, SAS automatically creates temporary flags FIRST.variable and LAST.variable (1 for true, 0 for false) in the PDV.
- Overwriting hazard: If non-BY variables share the same name across merged datasets, values from later datasets in the MERGE statement overwrite earlier ones.
- When a higher-level BY variable changes (FIRST.var1 = 1), SAS automatically forces FIRST.var2 = 1 for nested BY variables.
- The IN= dataset option creates temporary flags to distinguish dataset sources, allowing programmers to execute inner, left, or right joins.
3.3 Match-Merging with BY Statements & FIRST./LAST. Processing
Quick Answer: Match-merging combines datasets horizontally based on common key variables using
MERGEandBY. DuringBY-group processing, SAS creates temporary flagsFIRST.variableandLAST.variableto mark group boundaries.
Match-merging is one of the most powerful and tested features on the SAS Base Programming exam. Unlike vertical combination (SET), match-merging uses the MERGE statement accompanied by a BY statement to join observations side-by-side (horizontally) when values of common key variables match.
1. Prerequisites and Fundamentals of Match-Merging
To execute a match-merge, the DATA step must include a MERGE statement specifying the input datasets, followed by a BY statement naming the key variable(s).
data work.merged_data;
merge work.customers work.orders;
by CustomerID;
run;
Strict Requirements & Behaviors
- Sorting Requirement: Every dataset listed in the
MERGEstatement MUST be sorted by the variable(s) listed in theBYstatement. - PDV Combination: Observations with matching
BYvalues are merged into a single PDV row, aligning variables from both datasets. - Retention Across BY Groups: At the start of a new
BYgroup, non-BY variables in the PDV are set to missing. However, while processing multiple records within the sameBYgroup, SAS retains values in the PDV across iterations until theBYgroup changes.
2. Overwriting Hazard: Identical Non-BY Variable Names
If input datasets share non-BY variable names, values from datasets listed later in the MERGE statement will overwrite values from earlier datasets in the PDV!
/* Overwriting Example */
data work.dept_a; input ID Status $; datalines;
101 Active
; run;
data work.dept_b; input ID Status $; datalines;
101 Pending
; run;
data work.merged_status;
merge work.dept_a work.dept_b;
by ID;
run;
Result: In
work.merged_status, the value ofStatusforID=101will be "Pending" becausedept_bwas listed second in theMERGEstatement and overwrote "Active" fromdept_a. To prevent unexpected overwriting, use theRENAME=dataset option.
3. FIRST. and LAST. Temporary Variables
When a BY statement is present in a DATA step (with SET, MERGE, or UPDATE), SAS automatically creates two temporary numeric variables for every variable listed in the BY statement:
FIRST.byvar: Set to1on the first observation of aBYgroup; otherwise0.LAST.byvar: Set to1on the last observation of aBYgroup; otherwise0.
data work.sales_summary;
merge work.customers work.transactions;
by CustomerID;
/* Temporary variables FIRST.CustomerID and LAST.CustomerID exist in PDV */
if FIRST.CustomerID then AccountTotal = 0;
AccountTotal + Amount;
if LAST.CustomerID then output;
run;
Rules Governing FIRST. and LAST. Variables
- Temporary Status:
FIRST.andLAST.variables exist only in the PDV during execution and are never written to the output dataset. - Hierarchy Rule for Multiple BY Variables: When multiple variables are listed in the
BYstatement (e.g.,BY Region State;), higher-level variable transitions propagate down:- If
FIRST.Region = 1, thenFIRST.Stateis automatically set to 1, regardless of whether the state value changed. - If
LAST.Region = 1, thenLAST.Stateis automatically set to 1.
- If
Sample Data Evaluation Matrix
Consider a dataset sorted by Region and Store:
| Region | Store | FIRST.Region | LAST.Region | FIRST.Store | LAST.Store | Notes |
|---|---|---|---|---|---|---|
| East | 100 | 1 | 0 | 1 | 0 | First obs of East region and Store 100 |
| East | 100 | 0 | 0 | 0 | 1 | Last obs of Store 100 |
| East | 200 | 0 | 1 | 1 | 1 | Single record for Store 200; Last obs of East |
| West | 100 | 1 | 1 | 1 | 1 | Single record for West region and Store 100 |
4. Controlling Merge Joins with the IN= Option
The IN= dataset option creates a temporary numeric variable (valued 1 or 0) indicating whether a specific input dataset contributed data to the current PDV iteration.
data work.inner_join work.left_join;
merge work.clients (in=in_c) work.orders (in=in_o);
by ClientID;
/* Inner Join: record present in BOTH datasets */
if in_c and in_o then output work.inner_join;
/* Left Join: record present in Client dataset */
if in_c then output work.left_join;
run;
5. Exam Pitfalls & One-to-Many vs Many-to-Many Merges
- One-to-One Merge: Each key value appears once in each dataset. Smooth 1-to-1 row pairing.
- One-to-Many Merge: Key value appears once in lookup table, multiple times in transaction table. Lookup attributes repeat across all matched transactions.
- Many-to-Many Merge (DANGER): Key value appears multiple times in BOTH input datasets. SAS pairs records positionally within the key group until one dataset runs out, then retains the last values. This generates unpredictable, corrupt results and is almost always an exam question trap!
Consider the statement BY Region State City; in a match-merge step. If an observation represents the start of a new Region (FIRST.Region = 1), what are the values of FIRST.State and FIRST.City?
What type of processing occurs if a DATA step contains a MERGE statement listing two datasets but lacks a BY statement (data combined; merge ds1 ds2; run;)?
Datasets Sales1 and Sales2 both contain non-BY variable Amount. If merged using merge Sales1 Sales2; by ID;, which value of Amount appears in the output dataset for matching ID records?
Which subsetting IF statement correctly keeps only the final observation of each customer group when processing merge clients orders; by CustomerID;?