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

SQL Server多次内连接同表时如何正确返回无重复计数结果?

解决SQL计数因笛卡尔积膨胀的问题

嘿,我完全懂你遇到的这个坑!你现在得到49而不是期望的7,根本原因是两次关联cat_item_tb表导致了笛卡尔积——每一条ss=0的记录都会和对应ss=1的记录两两配对,7条×7条就变成了49条,自然计数就炸了。而且直接加distinct没用,是因为笛卡尔积已经让数据重复了,再去重也没法回到正确的统计逻辑里。

给你几个靠谱的解决方案,按效率和简洁度排序:

方案1:条件聚合(最推荐)

只关联一次cat_item_tb,用CASE语句分别统计不同ss值的唯一item_id,完全避免笛卡尔积:

SELECT
  COUNT(DISTINCT CASE WHEN ci.ss = 0 THEN ci.item_id END) AS count_ss0,
  COUNT(DISTINCT CASE WHEN ci.ss = 1 THEN ci.item_id END) AS count_ss1
FROM cat_tb
INNER JOIN item_tb ON cat_tb.cat_id = item_tb.cat_id
INNER JOIN cat_item_tb ci ON item_tb.item_id = ci.item_id;
  • 原理:通过一次表关联拿到所有相关记录,用CASE筛选出对应ss的item_id,再用DISTINCT确保每个item_id只被计数一次,完美解决重复和笛卡尔积问题。

方案2:子查询分别统计

如果更习惯拆分逻辑,可以用独立子查询分别计算两个计数,最后合并结果:

SELECT
  (SELECT COUNT(DISTINCT item_id) 
   FROM cat_item_tb 
   WHERE ss = 0 
     AND item_id IN (SELECT item_id FROM item_tb WHERE cat_id IN (SELECT cat_id FROM cat_tb))) AS count_ss0,
  (SELECT COUNT(DISTINCT item_id) 
   FROM cat_item_tb 
   WHERE ss = 1 
     AND item_id IN (SELECT item_id FROM item_tb WHERE cat_id IN (SELECT cat_id FROM cat_tb))) AS count_ss1;
  • 原理:每个子查询单独统计对应ss的唯一item_id,同时通过IN子句关联cat_tb和item_tb的筛选条件,不会产生交叉配对的问题。

方案3:左连接+去重计数

如果一定要用join的方式,可以用左连接分别关联不同ss的表,再用DISTINCT去重计数:

SELECT
  COUNT(DISTINCT ci0.item_id) AS count_ss0,
  COUNT(DISTINCT ci1.item_id) AS count_ss1
FROM cat_tb
INNER JOIN item_tb ON cat_tb.cat_id = item_tb.cat_id
LEFT JOIN cat_item_tb ci0 ON item_tb.item_id = ci0.item_id AND ci0.ss = 0
LEFT JOIN cat_item_tb ci1 ON item_tb.item_id = ci1.item_id AND ci1.ss = 1;
  • 原理:左连接不会强制要求两条表都有匹配,但因为我们用了DISTINCT,即使左连接产生了重复行,也只会保留唯一的item_id计数。

为什么你之前加DISTINCT没用?

因为你是在已经产生笛卡尔积的结果集上去重,比如原来的SQL里count(distinct cat_item_tb.item_id)确实会返回7,但count(distinct t.item_id)也会返回7,但如果你没加DISTINCT,就会得到49——可能你之前的尝试没把DISTINCT加到正确的位置?不过不管怎样,上面的方案从根源上避免了笛卡尔积,比事后去重更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:02:29