MySQL关联两表汇总年度销售数据时聚合结果偏高问题
原SQL存在的问题
- 连接类型选择错误:你用的
JOIN默认是内连接(INNER JOIN),只会返回在两张表中都匹配到的员工,2021年新入职、2020年没有销售记录的员工会被直接过滤,无法出现在结果里。 - 明细行直接关联产生笛卡尔积,这是销售额数值虚高的核心原因:如果某个员工2020年有3条销售记录,2021年有2条销售记录,按员工字段关联后会生成3*2=6条匹配记录,后续
SUM计算时单条销售记录会被重复累加多次,结果必然远大于实际值。 - 字段取值逻辑有漏洞:你直接取
sales20表的staff和region字段,2021年新员工在sales20中无对应数据,这两个字段会返回空值,不符合展示要求。
修正方案
核心原则是先单独聚合每一年的销售数据算好累计值,再做表关联,从根源上避免明细行交叉匹配产生的重复计算问题。
适用于支持全外连接的数据库(PostgreSQL、Oracle、SQL Server等)
先分别聚合两张表得到年度维度的员工销售汇总,再对汇总结果做全外连接,用COALESCE函数补全员工、区域字段的空值:
SELECT COALESCE(s20.staff, s21.staff) AS staff, COALESCE(s20.region, s21.region) AS region, s20.total_20, s21.total_21 FROM ( SELECT staff, region, SUM(amount) AS total_20 FROM sales20 GROUP BY staff, region ) s20 FULL OUTER JOIN ( SELECT staff, region, SUM(amount) AS total_21 FROM sales21 GROUP BY staff, region ) s21 ON s20.staff = s21.staff AND s20.region = s21.region
适用于不支持全外连接的数据库(如MySQL)
先通过UNION拿到两年所有出现过的员工+区域的全量去重名单,再分别左关联两年的聚合结果,兼容性更好:
WITH all_staff AS ( SELECT staff, region FROM sales20 UNION SELECT staff, region FROM sales21 ), sum20 AS ( SELECT staff, region, SUM(amount) AS total_20 FROM sales20 GROUP BY staff, region ), sum21 AS ( SELECT staff, region, SUM(amount) AS total_21 FROM sales21 GROUP BY staff, region ) SELECT a.staff, a.region, sum20.total_20, sum21.total_21 FROM all_staff a LEFT JOIN sum20 ON a.staff = sum20.staff AND a.region = sum20.region LEFT JOIN sum21 ON a.staff = sum21.staff AND a.region = sum21.region
如果业务上不需要区分员工的所属区域变动,只需要按员工维度统计两年销售额,把上述所有SQL里的
region字段从分组、关联条件中移除即可。
内容的提问来源于stack exchange,提问作者lyubomirsm
相关产品推荐
相关产品推荐

