proc sql

Proc sqlを極める(12) ーEXISTS句ー

SQLのEXIST句はテーブル(レコードの集合)を引数にとることができる述語(論理値を返す関数の一種)です。
対象のテーブルから別のテーブルに存在する、あるいは存在しないレコードを抽出するのに使いますが、
実務では特定の条件に合致する症例にフラグを立てるのに使うと便利だと思います。

EXISTS句

EXISTS句は指定した条件に合致するレコードが引数のテーブルに存在するかを調べることができます。
普通はwhere句の条件として、サブクエリを引数とするケースが多いと思います。
SASのin=オプションを使う場合と大体同じ働きをします。

活用例

併用薬の使用歴がある症例を抽出する

データセットdmとcmがあり、dmには患者背景情報、cmには併用薬の情報が格納されています。
dmに存在し、併用薬として薬剤3を使用したことがある症例に1を格納した変数drg3flgを作成したいとします。

DM
CM

SASで実施するのなら薬剤3のレコードを抽出して症例の重複を削除した中間テーブルを作成した後、dmにマージ。
inオプションで中間テーブルに存在する症例にはフラグをたてるといった流れになると思います。

proc sort data=dm ;by usubjid; run;
proc sort data=cm out=cm_tmp(keep=usubjid) nodupkey;
by usubjid;
where cmtrt="薬剤3";
run;
data wk1_sas;
merge dm
cm_tmp(in=a);
by usubjid;
if a then drg3fl=1;
else drg3fl=0;
run;

これと同等の処理をSQLで実施すると以下のようなクエリになります。
exists句でレコードが存在を確認し、case式を使って存在する場合は1, そうでない場合は0と読み替えます。
exists句の引数として薬剤3のレコードの集合を与えていますが、この時where句に”dm.usubjid = cm.usubjid”の条件を追加します。
この条件を追加しないとすべてのレコードにフラグがたってしまいます。

exists句は論理値を返す関数とみなすことができますので、case式の条件としてそのまま指定できます。
SASと違ってソート、マージの処理が不要であり、集合演算も一つの述語で表現できるので人によってはわかりやすいと感じる人もいるかもしれません。
SASのデータステップは集合演算といった概念がなく、マージで代用するしかありません。

proc sql noprint;
create table wk1_sql as
select dm.*,
case when exists (
select *
from cm
where dm.usubjid = cm.usubjid and
cm.cmtrt = "薬剤3") then 1
else 0
end as drg3flg
from dm;
quit;

特定の検査値を持つ症例を抽出する

検査値を格納したデータセットLBがあります。検査値AVALNの値がすべて5以上の症例に1、そうでない症例には0を格納した変数aval2flgをdmデータセットに追加します。

LB

「AVALNの値がすべて5以上の症例」というのは「5未満のAVALNが存在しない症例」と言い換えることができます。この考え方はとても重要です!

この条件で抽出するにはNOT EXISTS句を使います。EXISTS句の否定なので指定したレコードの集合に存在しないレコードを抽出できます。

proc sql noprint;
create table wk2_sql as
select dm.*,
case when not exists(
select *
from lb
where dm.usubjid = lb.usubjid and
avaln < 5) then 1
else 0
end as aval2flg
from dm;
quit;

今回紹介した実用例はすべてSASでもできますのでSQLでやらなくても良いですが、proc sqlを多用する人は知っていたほうが良いと思います。