最近、現場でIS NULL を書いて、え?と言われたので。
IS NULL と NOT EXISTS は、同じデータを抽出できる
前提
こんなテーブルがあったとします。
*がついているカラムが、PKとします。
T1_TBL
ID * | VAL |
---|---|
ID1 | VAL1 |
ID2 | VAL2 |
ID3 | VAL3 |
T2_TBL
NUM * | VAL | ID |
---|---|---|
1 | VAL1 | ID1 |
2 | VAL2 | ID2 |
抽出したい結果
T1_TBLに有るけど、T2_TBLに無い T1_TBLのレコードを取得したい。
こんな結果。
ID | VAL |
---|---|
ID3 | VAL3 |
IS NULL の場合
SELECT
*
FROM T1_TBL a
LEFT OUTER JOIN T2_TBL b
on a.ID = b.ID
WHERE b.NUM IS NULL
こう書くと、内部では以下のように疑似テーブルができます。
T1_TBL.ID * | T1_TBL.VAL | T2_TBL.NUM * | T2_TBL.VAL | T2_TBL.ID |
---|---|---|---|---|
ID1 | VAL1 | 1 | VAL1 | ID1 |
ID2 | VAL2 | 2 | VAL2 | ID2 |
ID3 | VAL3 | NULL | NULL | NULL |
で、WHERE句で、T2_TBL.NUM(PK)なので、本来NULLにならないけど、
NUM IS NULL条件を加えることで、NULLではない不要な行を省けます。
PK以外で、IS NULLを行うと、NULLのデータも抽出されてしまうので、
必ず、PKを指定します。
T1_TBL.ID * | T1_TBL.VAL | T2_TBL.NUM * | T2_TBL.VAL | T2_TBL.ID |
---|---|---|---|---|
ID3 | VAL3 | NULL | NULL | NULL |
NOT EXISTSの場合
SELECT
*
FROM T1_TBL a
WHERE NOT EXISTS(SELECT *
FROM T2_TBL b
WHERE a.ID = b.ID
)
ですね。
結果は、IS NULL と一緒です。
結論
分かり易さ?からすると、NOT EXISTS かな?と思います。
ただ、個人的な好みは、IS NULLです(笑)
あとは、パフォーマンスとの相談ですね。