ラベル マクロ: &SQLOBS の投稿を表示しています。 すべての投稿を表示
ラベル マクロ: &SQLOBS の投稿を表示しています。 すべての投稿を表示

2014年9月18日木曜日

変数値をマクロ変数に格納する方法「SQL編」



前回の続きで、今度はSQLプロシジャを使った方法を紹介。
(最後に注意点の記事リンクも貼ったので、そちらも要参照)


* サンプルデータ ;
data DT1;
input A$ B$ @@;
cards;
001 AA 002 BB 003 CC
run;

 
B
 001
 AA
 002
 BB 
 003
 CC 


上記変数A,Bの値をマクロ変数に格納します。

変数値をマクロ変数に格納 ;
proc sql noprint;
   select A, B  into :A1-, :B1- 
   from DT1;
quit;

%let OBS = &SQLOBS;

* ログにマクロ変数値を展開 ;
%macro MAC;
   %do i=1 %to &OBS;
       %put  &&A&i  &&B&i;
   %end;
%mend;
%MAC;

ログ
001  AA
002  BB
003  CC


SQLのINTOを使った方法(「こちら」を参照)

ただし「into :A1-, :B1-」という書き方はSAS9.3より前のバージョンでは使えないので
データステップ100万回「SQLでマクロ変数に値を格納する into: separated by」で紹介されている「into :A1-:A9999, :B1-:B9999」と値を大きくとっておくテクニックが使えます。

そしてもうひとつ重要な役割をするのが自動マクロ変数SQLOBS。
直前のSQLプロシジャが処理した行数が自動で入ってきます。(詳細は「こちら」を参照)
これを%DOループで利用してます。



一般的に使われるのはCALL SYMPUTXですが、SQLのINTOと&SQLOBSのコンボ技の方がスッキリとした文になるので個人的に好きな方法ではあります。


📝以下、落とし穴についての記事も要確認!

・数値をマクロ変数に格納すると丸められる可能性がある
・フォーマットが割り当てられた変数だと、フォーマットを当てた値がマクロ変数に格納される。

SQLプロシジャのINTO句で、前方に余計な半角スペースが入る場合がある。
・余計な半角スペースが入ってしまう場合の小技を紹介してます


2014年9月8日月曜日

自動マクロ変数「&SQLOBS」で、SQLが処理した行数を取得する



自動マクロ変数「&SQLOBS」には「SQLプロシジャが処理した行数」が格納される。
以下のようなイメージです。
  • select, from, where, group by, havingによって生成した結果の行数
  • updateによって更新した行数
  • deleteによって削除した行数
  • insertによって追加した行数
  • noprint, view, intoなどを使用している場合は挙動に変化あり。

具体例を見ていきましょう。


* サンプルデータ作成(obs数=10)  ;
data DT1;
   do A=1 to 10;
        output;
   end;
run;

*** 例① **************;
proc sql;
  select A
  from DT1;
quit;

%put --- &SQLOBS ---;
select, from句によって選択された10行が結果ビューアに出力される。
よって、SQLOBSには「10」が入る。
%putステートメントでログにSQLOBSの値を展開してるので、確認してみましょう。


*** ② **************;
proc sql;
  create table DT2 as
  select A
  from DT1;
quit;

%put --- &SQLOBS ---;
select, from句によって選択された10行がデータセットDT2に出力される。
よって、SQLOBSには「10」が入る。


*** ③ **************;
proc sql noprint;
  select A
  from DT1;
quit;

%put --- &SQLOBS ---;
注意が必要。
noprint結果ビューアへの出力を抑制。またcreate tableを指定していないので、データセットへも出力せず。
この場合、内部的には1行だけしか処理していないようで、SQLOBSには「1」が入る。
ちなみに、fromやwhere等によって選択される行が存在しない場合、SQLOBSに「0」が入る。


*** ④ **************;
proc sql noprint;
  select A into :A1-:A3
  from DT1;
quit;

%put --- &SQLOBS ---;
noprintが指定されてるけど、into句がある。
ここで指定してるinto句は、「変数Aを3行分、マクロ変数A1~A3に格納する」という指定。
ということでSQLOBSには「3」が入る。


*** ⑤ **************;
data DT3; set DT1; run;

proc sql noprint;
  delete from DT3
  where A>=8;
quit;

%put --- &SQLOBS ---;
noprintが指定されてるけど、delete句がある。
ここでは「A>=8」の3行を削除しています。
ということでSQLOBSには「3」が入る。


*** ⑥ **************;
data DT4; set DT1; run;

proc sql noprint;
  update DT4 set A=10 where A>=8;
quit;

%put --- &SQLOBS ---;
noprintが指定されてるけど、update句がある。
ここでは「A>=8」の3行を更新しています。
ということでSQLOBSには「3」が入る。


*** ⑦ **************;
proc sql ;
  create view DT5 as
  select A
  from DT1;
quit;

%put --- &SQLOBS ---;
注意が必要。
viewは特殊なデータなので、処理行数は取得できない。
ということでSQLOBSには「0」が入る。



オブザベーション数を取得する方法として、よく使われるので覚えておくと便利です。