一部の特殊な嗜好を持った悲しい人達が、仕事中に見てニヤニヤできればいいなぁっていう思いでやってる部分が大きいのである意味、ブログの主旨にあった記事かも。
今日、仕事中に、setステートメントの前に割り当てステートメントで、setで指定しているデータセット中に含まれる変数を指定するとlengthはどうなるかという話で恥を書く。
ようするに以下のコードを実行した際にデータセットがどうなるかって話。
data XXXX;
NAME="A";
set sashelp.class;
run;
まあ、実際やってみて貰えればわかるんですけど、僕はちょっと勘違いしてたんですよ。
そしたら、えぇ、こんなのBASEレベルの基本知識っすよとドヤ顔される。
誰とはいいませんけど
要するに、割り当てだろうが、setだろうが、先に入った値、変数でlengthが決まるという基本知識ですよ、ええ、SASの基本ですね、はいはい。うっかりしてましたってば。
例えば以下の2つのデータセットがあったとして
data X;
length A $1. B $5.;
A="1";B="1234";C=1;
run;
data Y;
length B $1. A $5.;
B="1";A="1234";D=2;
run;
Xを先にsetすると
data OUT1;
set X Y;
run;
よくみると、Aの2obs目が一文字目で切れてる。
確認してみると
データセットXの変数AのlengthがデータセットY由来にも適用されちゃってるわけですね。
逆に今度はYを先にsetすると
data OUT2;
set Y X;
run;
Bが切れるわけですよ。
どうすればいいのか?
いや、素直にlengthステートメントで指定すればいいんですよ。
切り捨てが起きうる状況の場合、必ずログに
こういうのがでるんで、そしたらlengthを調べて、十分な値にしてやればいいんです。
はい、でもそれだと面白くもなんともないんで、lengthステートメントを使わない方法を考えてみます。
たとえば変数が凄い多くあって、lengthが仕様で定義されてない場合とか面倒でしょ。
これも、指摘してきた人に指摘されたことですが、SQLのunionを使うと、大きい方にlengthを寄せてくれます。
つまり
proc sql;
create table OUT3 as
select * from X
union all corr
select * from Y
;
quit;
とすれば
おぉ!!
しかし、Xにしかない変数C、Yにしかない変数Dが落ちてやがる。
じゃあ、corrとればいいんでない?と思っちゃうかもしれないけど、変数情報が完全に同一でない
状況でcorrをつけないと、まあ、ひどいことになるから、興味のある人はやってみてください。
/*---------追記-----------------*/
matsuさんに突っ込まれました。「outer union corr」使えばいいやんと。
あ~、しまった、その通りです。ボケてましたよ…。駄目だなぁ。
というわけで、以下あんまり意味のない記事になってしまいましたが、
連結後の処理をSQLじゃなくて、データステップでやりたい場合?になるのかなぁ。
/*-----------------------------*/
じゃあどうするかということで、例えば2ステップですが、こんなんどうでしょう?
proc sql;
create view vw1 as
select * from X
union corr
select * from Y
;
quit;
data OUT4;
if 0 then set vw1;
set X Y;
run;
おぉ!ばっちし!!
多分そんなに遅くないし、どんなデータが来てもコードを変えずに実行できるし、なかなか面白いんじゃないですか?
多分、他にもやりようあるので、是非考えてみてください。
以上。
こんにちは。
返信削除outer union corrで繋げると変数落ちないと思います。
違ってたらすみません!
どうもです。いっつも、フォローしてもらってすみませんです。
返信削除仰るとおりです。
お馬鹿さんです。SQLもSASも1からやり直します