多表LEFT JOIN求和出现重复值问题求助(涉及4张业务表)
兄弟,你遇到的这个问题太典型了——多表LEFT JOIN后求和出现重复,本质是一对多关联导致的行膨胀:比如当tb_satker和tb_target是一对多关系时,主表的一条记录会被关联的子表数据重复带出,直接求和就会把数值反复计算,结果自然偏大。我结合你给出的表结构,给你两个最实用的解决方案:
解决方案一:先聚合子表,再关联主表(最推荐)
核心思路是:先对每个存在一对多关系的子表,按关联键(比如kode_satker)单独做聚合运算,得到每个kode_satker的唯一求和结果,再和主表tb_satker关联。这样就从根源上避免了行重复。
举个具体的SQL例子(假设还有另外两张表tb_actual和tb_budget,结构类似tb_target):
SELECT s.kode_satker, s.nama_satker, -- 用COALESCE处理无关联数据的情况,返回0而非NULL COALESCE(t.sum_target, 0) AS total_target, COALESCE(a.sum_actual, 0) AS total_actual, COALESCE(b.sum_budget, 0) AS total_budget FROM tb_satker s -- 先聚合tb_target的数据 LEFT JOIN ( SELECT kode_satker, SUM(jumlah) AS sum_target FROM tb_target GROUP BY kode_satker ) t ON s.kode_satker = t.kode_satker -- 同理聚合其他子表 LEFT JOIN ( SELECT kode_satker, SUM(actual_jumlah) AS sum_actual FROM tb_actual GROUP BY kode_satker ) a ON s.kode_satker = a.kode_satker LEFT JOIN ( SELECT kode_satker, SUM(budget_jumlah) AS sum_budget FROM tb_budget GROUP BY kode_satker ) b ON s.kode_satker = b.kode_satker;
解决方案二:用DISTINCT+窗口函数(适合需要保留明细的场景)
如果你需要同时查看子表的明细数据,又要得到正确的求和结果,可以用窗口函数结合DISTINCT,确保每个kode_satker只返回一次求和值:
SELECT DISTINCT s.kode_satker, s.nama_satker, t.id AS target_id, t.jumlah AS target_jumlah, -- 按kode_satker分区求和,确保每个分组的求和值唯一 SUM(t.jumlah) OVER (PARTITION BY s.kode_satker) AS total_target FROM tb_satker s LEFT JOIN tb_target t ON s.kode_satker = t.kode_satker;
关键注意事项
- 不要直接关联多个未聚合的一对多子表:比如同时关联
tb_target和tb_actual(都是一对多),会导致两张子表的数据产生笛卡尔积,行膨胀会更严重,求和结果偏差更大。 - 验证聚合结果:执行子查询单独查看聚合后的行数,确保每个
kode_satker只有一条记录,这样关联后就不会出现重复。
内容的提问来源于stack exchange,提问作者user2430933
相关产品推荐
相关产品推荐

