下面是两个查询(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结果的主要原因是什么,以及这两个查询之间的区别是什么?
答案 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
。