言語(PHP他)SQL
更新日 : 2020年9月1日
投稿日 : 2020年6月25日

WHERE文をどこにかけるか-全体か、JOIN内か?-

WHERE文をどこにかけるか-全体か、JOIN内か?-の画像

こんにちわ、PHPエンジニアのエンジニア婦人(@naho_osada)です。
PHPエンジニアとして9年~の経験があります。

今回はSQLが複雑になればなるほど、WHERE条件の「かかるところ」を意識しないと結果が異なって大事故になることがあるよ、というお話です。

ここではJOINの中でJOINする、複雑なSQL-相関サブクエリ-の考え方を例に書いていきます。

テーブル構造のサンプル
テーブル構造
staff
department

WHERE文をどこにかけるか

WHERE文を「どこにかけるか」によって取得できる結果が変わることがあります。

例えば

SELECT * FROM staff as stf
LEFT JOIN department as dep ON dep.department_id=stf.department

ここに「WHERE dep.department_name LIKE “%営業%”」を加えたい、「部署に営業の文字列を含むレコードを取得したい」場合、直感的に2パターンできるかなと予想されます。

パターン1:全体にWHERE

SELECT * FROM staff as stf
LEFT JOIN department as dep ON dep.department_id=stf.department
WHERE dep.department_name LIKE "%営業%"
全体にWHEREをかけて取得した結果

LEFT JOIN で連結した結果を元に、部署に「営業」を含むレコードを絞り込んだ結果

を表示しています。

パターン2:JOINにWHERE

SELECT * FROM staff as stf LEFT JOIN department as dep ON dep.department_id=stf.department
 AND dep.department_name LIKE "%営業%"
JOINにWHEREをかけて取得した結果

LEFT JOIN で部署に「営業」を含むレコードを連結した結果

を表示しています。LEFT JOIN なので名前に「営業」を含まない行もNULLで出力されます(INNER JOIN であればこのNULL行は削除されます)。

どちらがいいかは取得したデータをこの後どうしたいかによって変わるのだろうと思います。(今回の簡単な例では右のNULL行がいらなければINNER JOIN しようよという話でもありますね…)

まとめ:JOINにかかる条件はJOINに書いた方が無難

ケースバイケースではありますが、原則

JOINにかかる条件はJOINに入れる

です。ここではパターン2の方です。
同じようなことをやっていますが、上記2つのように結果が予想と異なってしまい、実際に欲しかったデータが正しく取得できない!ということにもなります。
今回は1つのテーブルの連結だけだったのでこの程度で済みますが、もし複数連結して副問い合わせでもあろうものなら…大事故の危険があります(そういったSQLを書かないのが一番ではありますが、書かないとならないことも往々にしてありますので)

今回私の遭遇したケースでは、ここでいうパターン2のような状態でNULLの行も欲しかったのに、最後にWHERE文で絞り込んでしまったので本来ならあるはずのNULL行がなくなり、その結果バグとなってしまいました。

以上、何かの参考になれば幸いです。

PR

※本サイトはアフィリエイトプログラムを利用して商品を紹介しています。