0

こんにちは、別の簡単な質問

条件付き結合に使用される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;
4

4 に答える 4

0

はい、わずか 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ステップで使用できますが、出力データセットには追加されません。」

于 2014-01-23T16:17:07.113 に答える
0

ルックアップ データセットを保持するために一時配列を使用する別のソリューションを次に示します。パフォーマンスはおそらく 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;
于 2014-01-19T12:56:22.267 に答える
0

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結合を引き続き実行します。

于 2014-01-17T15:44:13.927 に答える