2017-02-21 131 views
0

如果我有这个疑问:MYSQL - 使用并在JOIN与WHERE子句

select * from tableA 
left outer join tableB on tableA.id=tableB.id 
AND tableB.foo = 1 
where tableA.owner=10 

我获得了29倍的结果,但如果我动议进入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的不同方法的权威指南。任何人都可以向我解释这个吗?

此外,如果我在JOIN中执行类似AND tableB.foo = NULL的所有操作,即使表中的值不为空,我的所有tableB.foo字段在查询结果中都为NULL。在通过WHERE子句过滤之前,在JOIN子句中使用AND是否会更改FROM选择中的该字段?

+0

您可以在此处看到:http://stackoverflow.com/a/15706298/7416478 –

回答

1

您加入外表的所有条件都应该在JOIN子句中(如您的第一个查询)。将它放在WHERE子句中(如您的第二个查询)将OUTER JOIN隐式转换为INNER JOIN

至于你的问题AND tableB.foo = NULL这是不正确的MySQL语法。 NULLs需要special treatment,使用像IS NULL这样的运算符。您应该使用AND tableB.foo IS NULL

1

外连接与内连接的连接方式相同。另外,当没有匹配记录时,所有列设置为空的虚拟记录被加入(所以你仍然从结果中的第一个表中获得行)。

在您的第一个查询中,您正在查找具有相同ID和foo = 1的tableB中的匹配项。对于没有这种匹配的tableA中的记录,您仍然得到一个结果行(所有tableA字段为空)。

在第二个查询中,您在tableB中查找具有相同ID的匹配项。对于没有这种匹配的tableA中的记录,您仍然会得到一个结果行(所有tableA字段为空)。然后在你的where子句中,你只保留foo = 1的行。这就消除了所有外连接的记录(因为它们的foo为null),你就是你将要使用普通内连接的地方。

因此,请始终将所有条件放在ON子句中的外连接表上。 (虽然有一个例外;反加入,但您可以再次学习该模式。)