如何编写SQL查询计算各市场收银员与店员薪资总和(避免去重丢失数据)
解决方法:分别计算两类员工薪资再合并
你遇到的问题核心是直接关联三张表会产生笛卡尔积——比如一个收银员对应多个店员时,该收银员的薪资会被重复计算多次;而用SUM(DISTINCT)又会误把同薪资的不同员工当成同一个,漏掉应有的薪资。
正确的思路是:先分别计算每个市场的收银员总薪资、店员总薪资,再把这两个结果合并相加,这样就能避免重复计算和漏算。
完整SQL实现(用CTE让代码更清晰)
WITH cashier_salaries AS ( -- 先获取每个市场的唯一收银员,再计算薪资总和 SELECT m.market_id, SUM(c.salary) AS cashier_total FROM (SELECT DISTINCT market_id, cashier_id FROM market) m JOIN cashier c ON m.cashier_id = c.cashier_id GROUP BY m.market_id ), storekeeper_salaries AS ( -- 同理,获取每个市场的唯一店员,计算薪资总和 SELECT m.market_id, SUM(s.salary) AS storekeeper_total FROM (SELECT DISTINCT market_id, storekeeper_id FROM market) m JOIN storekeeper s ON m.storekeeper_id = s.storekeeper_id GROUP BY m.market_id ) -- 合并两个结果,计算总薪资 SELECT COALESCE(c.market_id, s.market_id) AS market_id, COALESCE(c.cashier_total, 0) + COALESCE(s.storekeeper_total, 0) AS total_salary FROM cashier_salaries c FULL JOIN storekeeper_salaries s ON c.market_id = s.market_id ORDER BY market_id;
为什么这个方法有效?
- 去重处理:通过
SELECT DISTINCT market_id, cashier_id确保每个市场的每个收银员只被统计一次,避免了笛卡尔积导致的重复计算;店员同理。 - 独立求和:分别计算两类员工的薪资总和,再相加,不会出现互相干扰的情况。
- 兼容性:用
FULL JOIN和COALESCE确保即使某个市场只有收银员或只有店员,也能正确计算总和(没有的那类薪资按0处理)。
验证结果
执行后会得到你预期的结果:
market_id | total_salary m1 | 6300 m2 | 4520
内容的提问来源于stack exchange,提问作者user334352353
相关产品推荐
相关产品推荐

