長いタイトルですが、SQLのいいとこ取りした便利技の紹介です。
Sample Data
data DT1;
length A $2. B $1.;
input A$ B$ ;
cards;
01 a
02 b
02 b
;
run;
data DT2;
length A $1. B $2.;
input A$ B$;
cards;
3 cc
4 dd
;
run;
DT1
DT2
|
サンプルデータをまずSETで結合してみます。
data OUT1;
set DT1 DT2;
run;
ログ
WARNING: 入力データセットによって、変数Bに複数の長さが指定されました。データの切り捨てが発生します。
|
結果を見ると、変数Bの値が、一部文字切れしちゃってますね。
これは、
「set DT1 DT2」 で最初に指定したデータセットDT1にある変数のlengthが、結合後のデータセットに割り当てられるからです。
つまり、変数Bのlengthが、DT1は「$1」、DT2は「$2」と異なっていますが、
上記青字の性質によって、結合時に「$1」が割り当てられます。
なので、DT2から持ってきた変数Bは、length「$1」に合わせて文字を切ってしまいます。
解決法
正攻法として、SETする時にlengthを設定しなおせばokですが、、、
data OUT2;
length A B $3.;
set DT1 DT2;
run;
|
「
SQLプロシジャ入門14:データセットを縦結合する【UNION】」で紹介した「OUTER UNION CORR」を使えば、
なんと結合するデータセットの中で最大のlengthを勝手に設定してくれます。
proc sql;
create table OUT3 as
select * from DT1
outer union corr
select * from DT2;
quit;
|
ただし、SETステートメントと異なる動きあり。
まず、以下のプログラムと結果を見てみましょう。
*** Sample Data ;
data DT1;
A = .;
run;
data DT2;
format A yymmdd10. ;
A = '01jan2015'd ;
run;
DT1
DT2
*** SETステートメントによる結合 ;
data OUT1;
set DT1 DT2;
run;
*** 「OUTER UNION CORR」による結合 ;
proc sql;
create table OUT2 as
select * from DT1
outer union corr
select * from DT2;
quit;
|
2つの結合結果を比較してみると、2行目の値が異なってますね。
これは「SETステートメント」の方は、format 「yymmdd10」 が割り当てられていて、
「OUTER UNION CORR」の方は、formatが割り当てられてないというだけで、
値自体は同じものです。
リファレンスから探せなくて確かではないですが、結合したデータセットの format, informat は、
- 「SETステートメント」: 最初のデータセットDT1にformat, informatが割り当てられてなければ、次のデータセットDT2のformat, informatを割り当てている模様。
- 「OUTER UNION CORR」: 最初のデータセットDT1のものを割り当てている模様。
他にも差異があるかもしれません。利用する際はいろいろテストしたり、期待通りの結果になるかご確認ください。
この違いを気にしないシチュエーションであれば、超便利なテクニックですね。