SQL:主にexistsについて

以下の2つのデータセットについて、Q2に同じあるオブザベーションの存在するQ1のオブザベーションを抽出するという問題をSQLで考えてみます。(単純な問題なので画像は省略です)

data Q1;
X='い';output;
X='ろ';output;
X='は';output;
run;

data Q2;
X='は';output;
X='へ';output;
X='ほ';output;
run;

答えはX='は'の1オブザベーションです。

まず、内部結合です。

proc sql noprint;
 create table A1 as
  select Q1.X
  from Q1 inner join Q2
  on Q1.X=Q2.X;
quit;

続いて inとサブクエリを使ってみます。

proc sql noprint;
 create table A2 as
  select X
  from Q1
  where X in (select X from Q2);
quit;

続いて、ややSQL慣れしていないと意味がとりにくいですが一般的にinより処理効率がよい
existと使ってみます

proc sql noprint;
 create table A3 as
  select X
  from Q1
  where exists (select 1 from Q2 where Q1.X=Q2.X);
quit;

です。
exists後のサブクエリのselect句に1とか適当に入れてますが、実はここのselect句はなんでもいいんです!*だろうが'あああ'とかでも結果に影響しません。
なんでかって言うと、existは、サブクエリの抽出条件により結果行が1行でも返ってくるかどうかを真偽として抽出をかけるからで、select句はSQLの構文上いるだけで意味ないんです。
ただ、データベースの製品によっては1のように定数にした方がパフォーマンス速いことがあるので、プログラマーによっては1と書きます。最近は*にしとく方が一般的らしいですが、どうなんでしょう。

最後に、今回はQ1で抽出したい変数と、Q2の変数が全く同じなので
intersectが使えます。

proc sql noprint;
 create table A4 as
  select X
  from Q1
  intersect
  select X
  from Q2;
quit;

intersectについては
「SQLで他のデータセットと共通、非共通のデータをとる(差集合 積集合) EXCEPT  INTERSECT」
を参照してください。

いや、SQLはほんとう、面白いし、奥深いし、頭使いますね。







0 件のコメント:

コメントを投稿