date関数やtime関数等はデータステップとSQLだと考え方が違うから注意という話

明けましておめでとうございます。

新年早々、ちょっとしたクイズです。

まず以下のデータセットがあるとします。

data a;
do i=1 to 10000000;
output;
end;
run;

次に2つのコードを示します。仮に全く同じ時間に実行した場合において
このコードの結果、できる2つのデータセットの内容は一致するでしょうか?しないでしょうか?

/*一つ目*/
data b;
set a;
time=time();
format time time.;
run;

/*2つ目*/
proc sql  ;
create table c as
select i,time() as time  format=time.
from a;
quit;

はい、まあ、問題にするってことは一致しないんですよ。

まず一つ目のデータステップでやった方の最初らへんと最後らへんの中身を見てみましょう。





















若干時間が違いますね。
データステップの場合、関数は、1obsごとに実行されるので、まさに
そのオブザベーションを処理した時間を掴みます。
よくあんのが、凄い時間のかかる処理を深夜にバッチで回したりして、翌朝みたら、
obsの途中から日付変わってるやん!ちくしょーみたいな話ですね。

次はSQLの方ですが、以下の通り




















全部おんなじ時間が入ってます。

なんでかっていうと、SQLプロシジャではdate,time,datetime等の関数は
SQLが実行される前に、日時を取得して、それを一律で関数の結果に返すという仕様を持ってます。
(わざわざ検証してないですが、たぶんtoday,weekday,holidayとか日時依存のやつは全部な気がする)

これをデータステップと同じように、そのobsが抽出された時間にしたければproc sqlにnoconstdatetimeオプションを
つけてやればOK。

proc sql noconstdatetime ;
 create table d as
 select i,time() as time  format=time.
 from a;
quit;


あるいは、実行される全てのSQLをずっとその仕様にしたいというなら
options nosqlconstdatetime;
としてやればOKです。元に戻すには
options sqlconstdatetime;
でOK。

データステップで、全obsに同じ時間を入れたい場合は、1obs目に取得してretainするか、
直前にマクロ変数に入れておいて展開するかになると思うので、こういう処理を書きたいなら
SQLでやった方が楽かもしんないですね。



以上。

さて、このブログも2013年にスタートしたので、今年の秋で丸4年です。
よくもまあ、データステップで何年も書けるなぁって自分で思います。
書きたいことを無責任に書き殴るスタイルだから、続いてるんだと思います。

最初の頃みると、月に37回とか記事あげてるんですね、思い返すと、毎日あんまり寝ずに書き続けてたんで、もう狂ってたとしか思えないですね。

今年も今まで通り、マイペースで書いたり休んだりでいくので宜しくお願いします。

また、よろしければ、是非、SASブログ初めてみませんか?
データステップでも、統計でも、グラフでも、ネタはなんでもいいので、書いてみると案外楽しいですよ。




0 件のコメント:

コメントを投稿