这两个查询之间的区别

时间:2014-07-10 19:39:16

标签: php mysql sql join left-join

下面是两个查询(WHERE查询和JOIN查询)。这两个查询有可能返回两个不同的结果集。

哪个查询可能会返回更多行?
必须存在哪些数据子集才能使查询返回不同数量的行?

WHERE查询:

SELECT COUNT(u.uid), r.name
FROM role r
LEFT JOIN users_roles ur ON r.rid = ur.rid
LEFT JOIN users u ON ur.uid = u.uid
WHERE u.status <> 0
GROUP BY r.rid

加入查询:

SELECT COUNT(u.uid), r.name
FROM role r
LEFT JOIN users_roles ur ON r.rid = ur.rid
LEFT JOIN users u ON ur.uid = u.uid AND u.status <> 0
GROUP BY r.rid

返回diff结果的主要原因是什么,以及这两个查询之间的区别是什么?

2 个答案:

答案 0 :(得分:4)

left outer join的逻辑如下。将第一个表中的所有行与第二个表中的所有行进行比较。如果任何对符合on条件,则保留它们。如果没有行与第一个表中的特定行匹配,则然后将该行保留在第一个表中并生成所有其他列NULL

此逻辑适用于所有情况。所以,如果你这样做:

select a.*
from a left join
     b
     on 1 = 0;

然后它会将所有行保留在a中,即使on子句的计算结果始终为false。从某种意义上说,过滤器没有效果。

您的查询中也发生了同样的事情。当你有

ON ur.uid = u.uid AND u.status <> 0

这是要保留前面表格中的所有行。如果匹配的状态为非零,则将该值用于u.status。否则,值为NULL

当你改为:

WHERE u.status <> 0

然后你真的说:左连接没有成功,状态&lt;&gt;写这个的“更安全”的方法是:

WHERE u.status <> 0 or u.status IS NULL

但是,将条件放在on子句中更清楚,因为它确实是left outer join的一部分。

答案 1 :(得分:3)

WHERE查询在加入后检查u.status <> 0 JOIN查询将u.status <> 0作为连接的一部分进行检查。

因此,如果u.status = 0 WHERE查询将不返回任何内容,而JOIN查询将返回,但会将users中的所有字段设置为NULL。

顺便说一句,COUNT(u.uid)将计算返回的非空uid的总数,而不是有多少不同的uid