MYSQL - 在JOIN和WHERE子句中使用AND

时间:2017-02-21 18:08:12

标签: mysql

如果我有这个问题:

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选择中的那个字段?

2 个答案:

答案 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子句中的外连接表上。 (但有一个例外;反连接,但你可以在另一次学习这种模式。)