如果我有这个问题:
select * from tableA
left outer join tableB on tableA.id=tableB.id
AND tableB.foo = 1
where tableA.owner=10
我得到29个结果,但是如果我将AND移动到WHERE子句中,如:
select * from tableA
left outer join tableB on tableA.id=tableB.id
where tableA.owner=10
AND tableB.foo = 1
然后我只得到17个结果。
在JOIN与WHERE子句中使用AND时,我已经四处寻找并且无法找到关于如何使用AND的明确指南。任何人都可以向我解释这个吗?
此外,如果我在JOIN中执行类似AND tableB.foo = NULL
的操作,则查询结果中的所有tableB.foo字段都为NULL,即使它们在表中不为null。在被WHERE子句过滤之前,在JOIN子句中使用AND是否会更改FROM选择中的那个字段?
答案 0 :(得分:1)
您在外部加入的表的所有条件都应该在JOIN
子句中(就像您的第一个查询一样)。将其放入WHERE
子句(与第二个查询一样)会隐式将OUTER JOIN
转换为INNER JOIN
。
至于你关于AND tableB.foo = NULL
的问题,这是不正确的MySQL语法。使用IS NULL
之类的运算符,NULL需要special treatment。您应该使用AND tableB.foo IS NULL
代替。
答案 1 :(得分:1)
外部联接与内部联接的连接方式相同。另外,当记录不匹配时,所有列都设置为null的虚拟记录将被连接(因此您仍然可以从结果中的第一个表中获取行)。
在第一个查询中,您正在查找tableB中具有相同ID且foo = 1的匹配项。对于tableA中没有此类匹配项的记录,您仍然会得到一个结果行(所有tableA字段都为null)。
在第二个查询中,您正在查找tableB中具有相同ID的匹配项。对于tableA中没有这种匹配的记录,您仍然会得到一个结果行(所有tableA字段为null)。然后在你的where子句中,你只保留foo = 1的行。这会解散所有外连接的记录(因为它们的foo为null),而你就是普通内连接的地方。
因此,始终将所有条件放在ON子句中的外连接表上。 (但有一个例外;反连接,但你可以在另一次学习这种模式。)