なぜRIGHT JOIN
?
NULL
サブクエリの結果に追加する可能性があります。これは、構成の一般的な落とし穴NOT IN
です。
この簡単なデモを考えてみましょう。
SELECT 5 NOT IN (VALUES (1), (2), (3)) --> TRUE
,5 NOT IN (VALUES (1), (2), (3), (NULL)) --> NULL (!)
,5 IN (VALUES (1), (2), (3)) --> FALSE
,5 IN (VALUES (1), (2), (3), (NULL)) --> NULL (!)
言い換えると、「少なくとも1つの要素が不明であり、5である可能性があるため、セットに含まれて
いるかどうかはわかりません。」5
条項は関連するだけ
なので(テストにも合格もしません)、まったく影響しません。WHERE
TRUE
NULL
FALSE
WHERE id IN (...)
しかし、それは影響します
WHERE id NOT IN (...)
この式は、右側のセットにが含まれるとすぐに修飾され
ません。
おそらく意図したとおりではありませんか?
NULL
解決
要件は
LoginInfosを持たないすべてのユーザーを選択します
これには、テーブルに行がないユーザーも含まれる可能性がありますlogin
。したがって、LEFT JOIN
2回必要です。また、1人のユーザーがに複数の行を持つことができるかどうかは定義されていないため、または:login
も必要です。DISTINCT
GROUP BY
SELECT DISTINCT u.*
FROM users u
LEFT JOIN login l ON l.user_id = u.id
LEFT JOIN logininfo i ON i.login_id = l.id
WHERE i.login_id IS NULL
これはすべての不測の事態をカバーします。あなたができる...
- ユーザーごとに最大1回のログイン
DISTINCT
が可能な場合は削除します。
- すべてのユーザーに対して少なくとも1つの行がある場合は、最初
LEFT JOIN
の行をに置き換えます。JOIN
login
この代替方法でNOT EXISTS
は、サブクエリを使用します。
ただし、テーブルにユーザーあたりの行数がいくつあっても機能しますlogin
。そして、それは前述の問題のいずれも示していませんNOT IN
:
SELECT u.*
FROM users u
WHERE NOT EXISTS (
SELECT 1
FROM login l
JOIN logininfo i ON i.login_id = l.id
WHERE l.user_id = u.id
)