SQL中使用sum与group by分组如何仅保留每组首行去重
分组统计场景下去除冗余行的实现方案
冗余根因定位
当前查询出现重复冗余行的核心原因是GROUP BY的分组字段和统计口径错配:
- 从SELECT字段的设计看,你本意是按「服务商、返现匹配日期、处理状态」为维度,聚合计算对应维度下的总返现金额
- 但分组语句中额外引入了
f_created_time字段,同一统计维度下的每条原始记录创建时间存在细微差异,会直接把本该合并为同一组的统计结果拆成多行,形成无意义的冗余行
具体实现方法
根据「每个统计分组仅保留1行首行数据、剔除同维度冗余行」的目标,可根据实际业务场景选择对应方案:
- 修正分组口径,从根源消除冗余
直接从GROUP BY子句中移除不参与统计、且会导致拆分的f_created_time字段,让分组维度和SELECT的非聚合字段完全匹配:
这种方案适合无创建时间维度统计需求的场景,可直接把同维度下的所有返现金额合并为单行结果,不会出现多余拆分。SELECT f_provider, SUM(f_rebate_amount) as total_cashback, DATE(f_match_time) as match_time, f_status FROM rebate_history GROUP BY f_provider, DATE(f_match_time), f_status - 自定义组内行序,筛选保留目标首行
如果业务上需要基于原始记录的创建时间顺序筛选每组首行,可通过窗口函数给每个分组内的行做序号标记,仅保留序号为1的目标行:
说明:窗口函数内的SELECT f_provider, total_cashback, match_time, f_status FROM ( SELECT f_provider, SUM(f_rebate_amount) OVER (PARTITION BY f_provider, f_status, DATE(f_match_time)) as total_cashback, DATE(f_match_time) as match_time, f_status, -- 按创建时间排序标记组内行序号,根据「首行」定义调整排序方向 ROW_NUMBER() OVER ( PARTITION BY f_provider, f_status, DATE(f_match_time) ORDER BY f_created_time DESC ) as row_seq FROM rebate_history ) t WHERE row_seq = 1ORDER BY方向可灵活调整——取最新创建的首行用DESC,取最早创建的首行用ASC。
内容的提问来源于stack exchange,提问作者user14747889
相关产品推荐
相关产品推荐

