You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Left join加WHERE多条件丢失0关联左表数据问题求解

enter image description here

问题背景

现有broadcast、contact两张表,需求为统计每个广播对应的收件人数量,要求即使没有对应收件人,也要展示全部广播列表。最初使用如下Left join查询可得到符合预期的结果:

SELECT b.id, b.brl_name, COUNT(c.broadcast_list_id) AS Recepients 
FROM broadcastlistsms b 
LEFT JOIN addcontact c ON b.id = c.broadcast_list_id 
GROUP BY b.id,b.brl_name;

两张表均包含created_by、isdeleted公共字段,isdeleted字段值为1代表对应联系人或广播已被删除。现需要过滤统计:仅统计指定用户创建、未删除的广播,关联统计同用户创建、未删除的联系人数量,仍需保留联系人数为0的广播条目。
使用如下带WHERE条件的查询时,无法返回联系人数为0的广播条目,未达到预期:

SELECT b.id, b.brl_name, COUNT(c.broadcast_list_id) AS Recepients 
FROM broadcastlistsms b 
LEFT JOIN addcontact c ON b.id = c.broadcast_list_id 
WHERE (b.createdby_id = 1 and b.isdeleted = 0) and (c.createdby_id = 1 and c.isdeleted = 0)
GROUP BY b.id,b.brl_name;

后续contact表还将新增3个类似isdeleted的标识字段,需要支持按这些字段做条件过滤后再统计计数。

问题原因

左连接(LEFT JOIN)的执行逻辑是:左表数据全部返回,右表匹配不到关联条件的行时,右表字段全部返回NULL。
如果把右表(contact表)的过滤条件写在WHERE子句中,会把右表字段为NULL的行全部过滤掉,本质上把左连接变成了内连接,自然无法保留联系人数为0的广播条目。

正确写法

把右表的过滤条件全部放到LEFT JOIN的ON子句后面,左表的过滤条件可以保留在WHERE中(也可以放到ON里,效果一致),写法如下:

SELECT b.id, b.brl_name, COUNT(c.broadcast_list_id) AS Recepients 
FROM broadcastlistsms b 
LEFT JOIN addcontact c 
  ON b.id = c.broadcast_list_id
  -- 右表所有过滤条件全部写在ON子句中,避免过滤掉左表无匹配的行
  AND c.createdby_id = 1 
  AND c.isdeleted = 0
  -- 后续新增的contact表过滤字段,直接在这里追加AND条件即可
  -- AND c.xxx_flag = 0
WHERE b.createdby_id = 1 
  AND b.isdeleted = 0
GROUP BY b.id,b.brl_name;

如果后续contact表新增其他过滤标识字段,直接在JOIN的ON块后面追加对应的AND判断条件即可,不会影响左表广播条目的保留。

补充说明:COUNT()函数统计时会自动忽略NULL值,所以匹配不到联系人的广播,计数会正确返回0,不需要额外做IFNULL类处理。

内容的提问来源于stack exchange,提问作者user19491662

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 19:06:45