こんにちは、別の簡単な質問
条件付き結合に使用されるproc sqlでは、sasデータステップに似たものがありますか
例えば
proc sql;
....
data1 left join data2
on first<value<last
quit;
これをsas datastepで複製できますか
お気に入り
data work.combined
set data1(in=a) data2(in=b)
if a then output;
run;
はい、わずか 7 行のコードで簡単な (しかし微妙な) 方法があります。
達成しようとしているのは、本質的に、do ループの set ステートメントで実行できる条件付きデカルト結合です。次のコードは、Dmitry のテスト データセットと、SUGI Paper 249-30の付録にあるコードの修正バージョンを使用しています。
data data1;
input first last;
datalines;
1 3
4 7
6 9
;
run;
data data2;
input value;
datalines;
2
5
6
7
;
run;
/***** by data step looped SET *****/
DATA CART_data;
SET data1;
DO i=1 TO NN; /*NN can be referenced before set*/
SET data2 point=i nobs=NN; /*point=i - random access*/
if first<value<last then OUTPUT; /*conditional output*/
END;
RUN;
/***** by SQL *****/
proc sql;
create table cart_SQL as
select * from data1
left join data2
on first<value<last;
quit;
結果が一致することは容易にわかります。
また、SAS 9.2のドキュメントから、「コンパイル時に、SAS は各データセットの記述子部分を読み取り、NOBS= 変数の値を自動的に割り当てます。したがって、SET ステートメントの前に NOBS= 変数を参照できます。変数はDATAステップで使用できますが、出力データセットには追加されません。」
ルックアップ データセットを保持するために一時配列を使用する別のソリューションを次に示します。パフォーマンスはおそらく Dmitry のハッシュベースのソリューションに似ていますが、これは 9.1 より前のバージョンの SAS (つまり、ハッシュ オブジェクトが最初に導入されたとき) をまだ使用しているユーザーにも機能するはずです。
Dmitry のサンプル データセットを再利用しました。
data have1;
input first last;
datalines;
1 3
4 7
6 9
;
run;
data have2;
input value;
datalines;
2
5
6
7
;
run;
/*We need a macro var with the number of obs in the lookup dataset*/
/*This is so we can specify the dimension for the array to hold it*/
data _null_;
if 0 then set have2 nobs = nobs;
call symput('have2_nobs',put(nobs,8.));
stop;
run;
data want_temparray;
array v{&have2_nobs} _temporary_;
do _n_ = 1 to &have2_nobs;
set have2 (rename=(value=value_array));
v{_n_}=value_array;
end;
do _n_ = 1 by 1 until (eof_have1);
set have1 end = eof_have1;
value=.;
do i=1 to &have2_nobs;
if first < v{i} < last then do;
value=v{i};
output;
end;
end;
if missing(value) then output;
end;
drop i value_array;
run;
出力:
value first last
2 1 3
5 4 7
6 4 7
7 6 9
これは、同等の SQL からの出力と一致します。
proc sql;
create table want_sql as
select * from
have1 left join have2
on first<value<last
;
quit;
run;
MERGE でこれを行う直接的な方法はありません。これは、SQL メソッドがどの SAS データ ステップ メソッドよりも明らかに優れている例の 1 つです。何を行うにも、より多くのコードが必要になり、場合によってはより多くの時間が必要になるからです。
ただし、データによっては、いくつかのアプローチが理にかなっている可能性があります。特に、フォーマットのマージ。
がかなり小さい場合data1
(たとえば、数百万のレコード)、それからフォーマットを作成できます。そのようです:
data fmt_set;
set data1;
format label $8.;
start=first; *set up the names correctly;
end=last;
label='MATCH';
fmtname='DATA1F';
output;
if _n_=1 then do; *put out a hlo='o' line which is for unmatched lines;
start=.; *both unnecessary but nice for clarity;
end=.;
label='NOMATCH';
hlo='o';
output;
end;
run;
proc format cntlin=fmt_set; *import the dataset;
quit;
data want;
set data2;
if put(value,DATA1F.)="MATCH";
run;
これは、非常data1
に大きい場合 (私のシステムでは数億行) でない限り、実行が非常に高速です。並べ替えを必要としないため、並べ替え時間を含めると、データ ステップ マージよりも高速です。主な制限の 1 つは、1 行につき 1 行しか表示されないことですdata2
。それが望ましい場合、これは機能します。の繰り返しが必要な場合data2
は、この方法ではできません。
行が重複している可能性がある場合data1
(つまり、開始/終了が互いに重複している 2 つの行)、これにも対処する必要があります。開始/終了は通常、重複することが許可されていないためです。すべての行に設定hlo="m"
し、一致しない行に「om」を設定するか、重複を解決できます。
ただし、パフォーマンスの問題がない限り、または希望どおりに機能しない場合を除き、コードがはるかに短く、読みやすいため、SQL結合を引き続き実行します。