为什么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 (!)
换句话说:
“我们不知道是否5
在集合中,因为至少有一个元素是未知的并且可能是 5。”
由于WHERE
仅在一个子句TRUE
中是相关的(既NULL
没有通过测试也没有FALSE
通过测试),所以它根本不会影响WHERE id IN (...)
。
但是会影响
WHERE id NOT IN (...)
只要右手集中有 a,
这个表达式就
永远不合格。
可能不像预期的那样?
NULL
解决方案
要求是
选择所有没有 LoginInfos 的用户
这可以包括在表中也没有行的用户login
。因此,我们需要LEFT JOIN
两次。而且由于没有定义一个用户是否可以在 中拥有多行login
,我们还需要DISTINCT
or 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
这涵盖了所有可能发生的情况。你可以...
- 如果每个用户最多
DISTINCT
只能登录一次,请删除。
- 如果每个用户至少
LEFT JOIN
有一行,则替换第一个。JOIN
login
这种替代方案使用NOT EXISTS
子查询。
但无论 table 中每个用户可以有多少行,它都有效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
)