SQL按pais_id、codigo字段group by未合并重复记录问题咨询
问题排查与解决方法
未正确分组的原因
- GROUP BY子句包含了过多非目标分组字段。你当前需求是仅按
pais_id、codigo两个字段分组,但你在GROUP BY中额外添加了r.id、d.cod_fac、d.montante、r.importe等多个字段,只要这些字段的值存在差异,哪怕pais_id和codigo完全一致,也会被拆分为独立的分组行,自然不会合并。 - SELECT中定义的
codigo是动态拼接的计算列,部分数据库不支持在GROUP BY中直接引用SELECT里定义的别名,需要把拼接逻辑同步到GROUP BY中,或通过子查询/CTE先计算出codigo再执行分组。 - SELECT中未被纳入GROUP BY的字段没有使用聚合函数,不符合SQL分组的语法规则(严格模式下该SQL甚至会直接报错),也会导致分组逻辑不符合预期。
解决方法
首先你需要先明确分组后其他字段的聚合规则:比如数值类字段是求和、取最大值/最小值,日期类字段取最早/最晚,字符串类字段取任意值还是拼接合并,根据你的业务需求选择对应的聚合函数(SUM/MAX/MIN/STRING_AGG等)。
参考实现SQL如下:
-- 先计算出所有基础字段和codigo,再在外层执行分组 SELECT MAX(t.fecha_remesa) AS fecha_remesa, -- 示例:取最新的日期,可根据需求调整 MAX(t.abreviatura) AS abreviatura, MAX(t.cheque) AS cheque, SUM(t.importe) AS importe, -- 示例:金额求和,可根据需求调整 MAX(t.oficina) AS oficina, MAX(t.cod_fac) AS cod_fac, SUM(t.montante) AS montante, -- 示例:金额求和,可根据需求调整 MAX(t.entidad) AS entidad, t.pais_id, MAX(t.prasa) AS prasa, t.codigo FROM ( SELECT r.fecha_remesa, (SELECT m.abreviatura FROM Moneda m WHERE r.moneda_id=m.id) AS abreviatura, CASE WHEN r.tipo_doc=101 THEN 'CHK' ELSE 'TRV' END AS cheque, r.importe, r.oficina, d.cod_fac, d.montante, r.entidad, d.pais_id, CASE WHEN d.cod_fac=2 THEN 'I' WHEN d.cod_fac=1 THEN 'S' ELSE '' END AS prasa, ('9635CLR' || to_char(er.fecha_procesado, 'YYMMDD') || r.digito_remesa) AS codigo FROM remesa r LEFT JOIN documento d ON d.remesa_id = r.id INNER JOIN envio_remesa er ON er.id = r.envio_remesa_id WHERE er.fecha_procesado >= TO_DATE('2021-09-07','YYYY-mm-DD') AND er.fecha_procesado < TO_DATE('2021-09-07','YYYY-mm-DD') + 1 ) t -- 仅按两个目标字段分组 GROUP BY t.pais_id, t.codigo;
你可以根据实际业务需要,调整外层SELECT中的聚合函数,如果你不需要合并金额只是取其中一条的值,把SUM换成MAX或者MIN即可。
内容的提问来源于stack exchange,提问作者okjfokjrf
相关产品推荐
相关产品推荐

