Hash Object VS SQL

SASのHash ObjectをSQLと比較したものを記事にしました。

 

  • SQLとの比較

以前の記事に書いた通り、 SASのHash Objectはプログラム実行時にデータセットをメモリに格納し、キー、データの単位でテーブルルックアップを実行するオブジェクトになります。(下図参照)

 

f:id:essbase:20201027141912p:plain

Hash Objectイメージ

 Hash Objectのテーブルルックアップは基本的にFIND()メソッドを実行し、Left joinの挙動でルックアップを実行します。

 

set <データセットA>;

rc=<データセットB>.find();

 

上記の例ではデータセットAに対してデータセットBの変数の内容で更新をします。

SQLでは実行文に項目名の羅列が必要ですが、Hash Objectではその必要がありません。

 

今回はHash ObjectのテーブルルックアップをSQLのJOINに置き換えた場合を想定して掲載しております。それでは見ていきましょう。

Left Join

f:id:essbase:20201027141010p:plain

Left Join

下の例はHash ObjectでLeft Joinをしたものになります。FIND()メソッドを使用してprimaryデータセットに対してsecondaryデータセットのオブザベーションを追加更新しています。

 

_iorc_=sec.find();

 

ちなみに上の_IORC_変数は宣言してもSASデータセットに直接書き込まれない自動変数です。SASシステム内で管理されている変数でありユーザが直接更新しても内部で保持しているカウンタに影響せず、かつ使用後にdropする必要がなく大変便利なので使用しています。

 

if _iorc_ ne 0 then call missing(y);

 

call missingステートメントではFIND()メソッドで合致しなかったオブザベーションに欠損値を代入しています。

 

例:Hash Objectでルックアップ

data primary;

input number;

cards;

10001

10002

10009

10003

10004

10005

;

run;

 

data secondary;

input number y;

cards;

10001 11

10003 12

10004 13

10005 17

;

run;

 

data main;

if _N_=1 then

do;

 

if 0 then

set secondary;

dcl hash sec(dataset:"secondary") x();

sec.definekey("number");

sec.definedata("number", "y");

sec.definedone();

 

x.definekey("number");

x.definedata("number", "y");

x.definedone();

 

dcl hiter seci("sec");

end;

set primary;

_iorc_=sec.find(); *1;

if _iorc_ ne 0 then call missing(y);*2;

 

run;

Inner Join

f:id:essbase:20201027140628p:plain

inner join

下の例はHash ObjectでInner Joinをしたものになります。FIND()メソッドを使用して

値が0、つまり結合対象のデータセット双方に合致するオブザベーションのみを出力しています。

if _iorc_ = 0 then output;

 

data primary;

input number a;

cards;

10001 1

10002 2

10009 9

10003 3

10004 4

10005 5

;

run;

 

data secondary;

input number b;

cards;

10001 11

10003 12

10004 13

10005 17

;

run;

 

data main;

if _N_=1 then

do;

 

if 0 then

set secondary;

dcl hash sec(dataset:"secondary") x();

sec.definekey("number");

sec.definedata("number", "b");

sec.definedone();

 

x.definekey("number");

x.definedata("number", "a");

x.definedone();

 

dcl hiter seci("sec");

end;

set primary;

_iorc_=sec.find();*1;

if _iorc_ = 0 then output;*2;

 

run;

 

次回はFULL JOINについて詳しく紹介します。