如何使用COUNT()关联其他表作为条件查询无封禁记录的用户
嘿,这个需求很常见!要找出那些从来没被封禁过的用户,用COUNT()函数来实现的话,我给你分享两种实用的写法,还会讲清楚背后的逻辑:
方法1:LEFT JOIN + COUNT()
这是最常用且性能不错的写法,先通过左连接关联两张表,再统计封禁记录数筛选目标用户:
SELECT u.id, u.name FROM user u LEFT JOIN user_ban ub ON u.id = ub.user_id GROUP BY u.id, u.name HAVING COUNT(ub.id) = 0;
逻辑解释
LEFT JOIN会保留user表的所有记录,哪怕这个用户在user_ban里没有对应条目。COUNT(ub.id)只会统计user_ban中实际存在的id值(NULL会被COUNT忽略),所以当统计结果为0时,就说明这个用户完全没有被封禁过。
方法2:子查询结合COUNT()
如果觉得JOIN的写法有点绕,也可以用子查询直接统计每个用户的封禁次数,再筛选次数为0的:
SELECT u.id, u.name FROM user u WHERE (SELECT COUNT(*) FROM user_ban ub WHERE ub.user_id = u.id) = 0;
逻辑解释
这里的子查询会为user表中的每个用户单独计算对应的封禁记录总数,当这个总数是0时,就代表该用户从未被封禁。不过要注意,当用户表数据量很大时,这种写法的性能可能不如第一种,因为它要为每个用户执行一次子查询。
关键注意点
- 别用
COUNT(*)代替COUNT(ub.id)!如果用COUNT(*),LEFT JOIN产生的NULL行也会被统计进去,结果就会出错,永远筛选不到目标用户。 - 如果你的数据库支持,也可以用
NOT EXISTS的写法(虽然没用到COUNT()),不过既然要求用COUNT(),上面两种就完全满足需求啦。
内容的提问来源于stack exchange,提问作者Игорь Быстревский
相关产品推荐
相关产品推荐

