質問: 添付の画像は MS SQLServer上のあるテーブルの登録状況です。 青枠で囲った項目の組み合わせが、論理的なキーであり 当該の組み合わせが 当日時点で有効か非有効かを管理するためのマスタとなっています。 本日時点の青枠の組み合わせで、VALIDが1(TRUE)になっているものだけを抽出したいのですが NULL値を含む項目を結合したINNER JOINが正規結果を取得できない理由から 困っています。 ![画像の説明をここに入力](https://i.stack.imgur.com/peJTM.png) 期待のSELECT結果は、1.2.3.6.7.8.9ですが、下記発行では 2.3.6.7.8.9です。 ``` SELECT A.* FROM SMD_M_FDSTRBT A INNER JOIN (SELECT FORMID, DSTTYPE, DPTID, ROLEID, MAX(YMDSTART) AS YMDSTART FROM SMD_M_FDSTRBT WHERE YMDSTART <= CONVERT(VARCHAR, GETDATE(), 112) GROUP BY FORMID, DSTTYPE, DPTID, ROLEID) B ON B.FORMID=A.FORMID AND B.DSTTYPE=A.DSTTYPE AND B.DPTID=A.DPTID AND B.ROLEID=A.ROLEID AND B.YMDSTART=A.YMDSTART WHERE A.VALID=1 ORDER BY A.FORMID, A.DSTTYPE ``` ありきたりの問題ですが、どういった発行を行えば 1行目を含め、4.5行目は含めない結果を得られるのでしょうか?
回答: SQLでは三値論理を採用しているため、`NULL`と`NULL`を比較しても`TRUE`とはなりません。 ですので結合条件の`B.DPTID=A.DPTID`を ``` B.DPTID = A.DPTID OR (B.DPTID IS NULL AND A.DPTID IS NULL) ``` のように場合分けする必要があります。 ですがこのような変則的結合条件は実行時の効率を落としますので、DBの設計を見直した方がよいでしょう。たとえば`NULL`の代わりに`''`を使用するなどの方法があります。