主表与两个事实表关联后按产品维度聚合AMT1的SQL问题
解决多表关联后的聚合错误问题
你遇到的核心问题是多对多关联导致的笛卡尔积——直接关联三张表时,Table2中同一个ID1的多条记录会和Table3中对应ID的多条记录交叉匹配,导致Table2的AMT1被重复计算,最终聚合结果失真。而且从你的目标输出来看,其实不需要用到Table3的数据(结果只涉及Product和Amt1),所以可以简化逻辑来得到正确结果。
正确的实现语句
我们只需要关联Table1和Table2,再按Product维度聚合Amt1即可:
SELECT a.Product, SUM(b.AMT1) AS Amt1 FROM [dbo].[Table_1] a LEFT JOIN [dbo].[Table_2] b ON a.ID = b.ID1 WHERE b.ID1 IS NOT NULL -- 过滤掉Table1中未匹配到Table2的P3记录 GROUP BY a.Product ORDER BY a.Product;
逻辑说明
- 先通过
LEFT JOIN关联Table1和Table2,确保Table2的每条记录只匹配一次对应的Table1数据,不会产生多余的交叉行; - 按
Product分组后用SUM(b.AMT1)求和:- P1对应Table1的ID=1和ID=2,Table2中ID1=1的Amt1总和是
10+20+30=60,ID1=2的Amt1是20,合计80; - P2对应Table1的ID=3,Table2中ID1=3的Amt1是
10,合计10; WHERE b.ID1 IS NOT NULL会过滤掉Table1中没有匹配到Table2的P3,和你的目标输出完全一致。
- P1对应Table1的ID=1和ID=2,Table2中ID1=1的Amt1总和是
扩展场景:如果需要同时聚合Table3的Amt3
如果后续需求要同时统计Amt1和Amt3,必须先分别对Table2和Table3按ID聚合,再和Table1关联,彻底避免笛卡尔积:
WITH AggTable2 AS ( SELECT ID1, SUM(AMT1) AS TotalAmt1 FROM [dbo].[Table_2] GROUP BY ID1 ), AggTable3 AS ( SELECT ID3, SUM(AMT3) AS TotalAmt3 FROM [dbo].[Table_3] GROUP BY ID3 ) SELECT a.Product, ISNULL(at2.TotalAmt1, 0) AS Amt1, ISNULL(at3.TotalAmt3, 0) AS Amt3 FROM [dbo].[Table_1] a LEFT JOIN AggTable2 at2 ON a.ID = at2.ID1 LEFT JOIN AggTable3 at3 ON a.ID = at3.ID3 WHERE at2.ID1 IS NOT NULL GROUP BY a.Product, at2.TotalAmt1, at3.TotalAmt3;
这样每个ID的聚合值只会被计算一次,不会因为多表关联重复累加。
内容的提问来源于stack exchange,提问作者Revathi
相关产品推荐
相关产品推荐

