LEFT JOIN搭配COUNT GROUP BY时左表NULL记录未全部显示问题
问题根因
查询返回结果缺失的核心错误是GROUP BY字段选择错误:
- 当前语句使用右表
Contacts的c.broadcastlist_id作为分组依据 - LEFT JOIN的规则是:左表未匹配到右表数据的行,所有右表字段值均为
NULL - 测试数据中id=3、id=4的广播列表均无关联联系人,这两行的
c.broadcastlist_id值都是NULL,GROUP BY会将所有NULL值合并为同一个分组,最终只会返回1条计数为0的记录,无法区分两条无关联联系人的左表数据。
额外说明:在标准SQL模式及MySQL默认开启ONLY_FULL_GROUP_BY的环境下,你当前的写法本身就不符合语法要求——SELECT列表中的非聚合字段必须全部出现在GROUP BY子句中,你查询了b.id、b.name却未将其加入分组,本身就存在逻辑隐患。
修正语句
分组必须使用左表Broadcastlists的唯一标识字段(主键b.id,兼容严格模式可同时加入b.name),保留原有COUNT右表字段的写法即可,未匹配到联系人的记录会自动统计为0:
SELECT b.id, COUNT(c.broadcastlist_id) AS Recepients, b.name FROM Broadcastlists b LEFT JOIN Contacts c ON b.id = c.broadcastlist_id GROUP BY b.id, b.name;
执行后将返回预期的4条结果:
- id=1,Recepients=2,name=Test 1
- id=2,Recepients=3,name=Test 2
- id=3,Recepients=0,name=Test 4
- id=4,Recepients=0,name=Test 5
大表场景优化写法
如果Contacts表数据量较大,可以先在子查询中完成联系人数量的聚合统计,再和广播列表做左连接,避免两表全量连接产生冗余数据,执行效率更高:
SELECT b.id, IFNULL(c.contact_count, 0) AS Recepients, b.name FROM Broadcastlists b LEFT JOIN ( SELECT broadcastlist_id, COUNT(*) AS contact_count FROM Contacts GROUP BY broadcastlist_id ) c ON b.id = c.broadcastlist_id;
内容的提问来源于stack exchange,提问作者user19350831
相关产品推荐
相关产品推荐

