Combining Data Sets with SET and MERGE
Prerequisites: Choosing rows and columns
The examples in this lesson use two small data sets:
data customers;
input id name $;
datalines;
1 Ada
2 Alan
3 Grace
;
run;
data orders;
input id amount;
datalines;
1 50
1 20
3 75
4 10
;
run;
Stacking with SET
Listing several data sets on one SET statement concatenates them —
all rows of the first, then all rows of the second:
data q1;
input month $ sales;
datalines;
Jan 100
Feb 120
;
run;
data q2;
input month $ sales;
datalines;
Apr 90
;
run;
data half;
set q1 q2;
run;
proc print data=half noobs;
run;
month sales
Jan 100
Feb 120
Apr 90
Variables that exist in only one data set are missing in rows from the
other. Add a BY statement (with sorted inputs) to interleave rows in
sorted order instead.
Match-merging with MERGE and BY
MERGE with BY joins rows that share a key. Both data sets must be
sorted by the key (these already are):
data joined;
merge customers(in=in_cust) orders(in=in_ord);
by id;
from_cust = in_cust;
from_ord = in_ord;
run;
proc print data=joined noobs;
run;
id name amount from_cust from_ord
1 Ada 50 1 1
1 Ada 20 1 1
2 Alan . 1 0
3 Grace 75 1 1
4 10 0 1
- A plain
MERGEkeeps every key from both sides (a full outer join). IN=creates a temporary flag that is 1 when the current row came from that data set. (The flags aren't saved, so this example copies them into real variables to show them.)- One-to-many works naturally: Ada's name is repeated for both orders.
Choose rows with the flags:
| Statement | Result |
|---|---|
if in_cust and in_ord; |
inner join — ids 1 and 3 |
if in_cust; |
left join — every customer |
if in_cust and not in_ord; |
customers without orders — id 2 |
if in_ord and not in_cust; |
orders with unknown customers — id 4 |
Common mistakes
- Unsorted inputs —
ERROR: BY variables are not properly sorted. RunPROC SORTon each data set first. - Same variable name in both (other than the key) — the value from
the data set listed last wins, silently. Rename one with
(rename=...). - Many-to-many merges — when both sides repeat a key, SAS writes
NOTE: MERGE statement has more than one data set with repeats of BY values.and pairs rows one by one, which is almost never what you want. UsePROC SQLfor many-to-many joins. - Keys with different lengths or types — make them match before merging.
Practice
Using customers and orders, create a data set of customers who have
never ordered.
Show solution
data no_orders;
merge customers(in=in_cust) orders(in=in_ord);
by id;
if in_cust and not in_ord;
keep id name;
run;
proc print data=no_orders noobs;
run;
id name
2 Alan