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

三表INNER JOIN查询重复数据:John薪资与收款求和结果异常

解决三表连接导致聚合结果偏大的问题

这个问题我经常碰到——当你直接关联多个存在一对多关系的表时,笛卡尔积会让聚合计算重复统计数据,最终结果自然就偏大了。

问题原因分析

你当前的SQL直接把Customers和Salary、Receipts做内连接,假设John(Id=1)在Salary中有1条记录、Receipts中有1条记录,连接后是1条数据,结果没问题;但如果John在Salary中有多条记录,Receipts中也有多条记录,连接后会生成「薪资记录数×收款记录数」条数据,每条薪资会被重复统计N次(N是收款记录数),每条收款会被重复统计M次(M是薪资记录数),SUM出来的数值就会是实际值的数倍。

正确的解决方案

先分别对Salary和Receipts按客户ID聚合求和,得到每个客户的总薪资和总收款,再和Customers表关联,这样就彻底避免了笛卡尔积的问题。

具体SQL代码如下:

SELECT 
    cus.Name,
    COALESCE(sal.TotalSalary, 0) AS Salary,
    COALESCE(re.TotalReceipts, 0) AS Received
FROM Customers cus
LEFT JOIN (
    -- 先计算每个客户的薪资总和
    SELECT Id, SUM(Amount) AS TotalSalary
    FROM Salary
    GROUP BY Id
) sal ON cus.Id = sal.Id
LEFT JOIN (
    -- 再计算每个客户的收款总和
    SELECT Id, SUM(Amount) AS TotalReceipts
    FROM Receipts
    GROUP BY Id
) re ON cus.Id = re.Id
WHERE cus.Id = 1;

代码说明

  1. 子查询聚合:两个子查询分别对Salary和Receipts按Id(关联Customers的字段)分组求和,确保每个客户在子查询中只有一条汇总记录。
  2. LEFT JOIN + COALESCE:使用LEFT JOIN可以兼容客户没有薪资或收款记录的情况,COALESCE把NULL值替换为0,结果更符合业务预期。
  3. 精准过滤:最后通过WHERE cus.Id=1筛选John的数据,得到准确的总和。

用你提供的测试数据执行这段SQL,会得到正确结果:

NameSalaryReceived
john300500

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:19:22