【发布时间】:2017-06-14 15:48:05
【问题描述】:
我有 2 个包含相同键 p_id 的表:
test1 test2
+-------------+ +----------------------+
| p_id | name | | o_id | name | p_id |
+-------------+ +----------------------+
| 1 | Paul | | 1 | London | 1 |
| 2 | Marc | | 2 | Paris | 1 |
+-------------+ +----------------------+
现在我想从 test1 中获取与 test2 无关的所有条目。
在上面的示例中,我已经抽象了我的表,所以RIGHT JOIN 是不可能的(实际上我必须加入 4 个表)。
SELECT a.*,b.*
FROM test1 a
LEFT JOIN test2 b
ON a.p_id=b.p_id
WHERE b.p_id NOT IN(SELECT DISTINCT p_id FROM test2);
我希望有p_id=2 的一行。但是我得到一个空的结果。
当我将代码更改为:
SELECT a.*,b.*
FROM test1 a
LEFT JOIN test2 b
ON a.p_id=b.p_id
WHERE a.p_id NOT IN(SELECT DISTINCT p_id FROM test2);
然后它工作正常。但为什么?我认为首先处理LEFT JOIN(结果为1行),然后处理WHERE(在test2中未找到p_id,所以b.p_id是null-null不在子选择中- 结果仍然是 1 行)。
有人能解释一下这种行为吗?
【问题讨论】:
-
我没有发现任何问题。您的 LEFT JOIN 在第二个表中获得 2 行 p_id=1 但随后您将子查询中的那些排除在外
-
@RaymondNijland :抱歉,这是不正确的。我已经检查了您的建议,现在我得到了 2 行,其中设置了 p_id 和 test1.name,其他列为空。
-
@Mihai :这是不正确的。 Left Join 的结果是 3 行(2 行 p_id=1 和 1 行 p_id=2),然后我排除了 p_id=1 的两者。
-
@RaymondNijland 在左连接的 rhs 表上具有 where 条件不会自动将左连接变为内部连接;只有需要 rhs 表中的非空值的条件才会这样做。
-
@Uueerdo 您的评论通常是正确的,但在这种情况下,第一个 SQL 语句中外连接到表的谓词确实是“将左连接变为内连接”,因为 NULL(返回从外部连接到不匹配的行)既不在 p_id 列表中,也不在 p_id 列表中。 (试试这个插图:当 null 不在 (1, 2, 3) 中时选择大小写,然后在 (1, 2, 3) 中为 null 时选择大小写,然后在 (1, 2, 3) 中选择大小写,然后在‘in’ else 'neither' end 中选择 case)