无需使用CTE如何按DepositeDate列正确分组聚合金额的SQL实现
问题根因
你现有查询的结果异常,核心原因是分组依据和展示的日期口径不匹配:
- 你在SELECT中把原始的
DepositeDate(大概率是带时分秒的datetime类型)转成了仅保留年月日的DATE类型做展示 - 但GROUP BY语句用的是未做转换的原始
DepositeDate字段做分组键 - 这就导致同属一个自然日、但时分秒不同的记录会被拆成不同的分组,每个分组单独计算金额,最终就会出现多个相同日期的结果行,每个行的金额仅对应该分组下的记录累加值,而不是全天的总金额
无需CTE的修复方案
只需要把GROUP BY的分组口径,调整成和SELECT展示的日期口径一致即可,完全不需要CTE、嵌套子查询这类复杂写法:
方案1:分组时使用和SELECT完全一致的转换表达式
直接在GROUP BY里重复CAST转换逻辑,让所有同个自然日的记录被划分到同一组:
SELECT CAST(DepositeDate AS DATE) AS DepositeDate, SUM(TotalAmount) AS Amount FROM Payment GROUP BY CAST(DepositeDate AS DATE)
执行后就会得到你期望的聚合结果:同个自然日的所有金额会被累加,不会出现重复的日期行。
方案2:按SELECT列的位置分组(更简洁)
主流数据库(MySQL、PostgreSQL、SQL Server等)都支持直接引用SELECT列表的列序号做分组依据,因为第一列就是转换后的日期,直接写GROUP BY 1即可:
SELECT CAST(DepositeDate AS DATE) AS DepositeDate, SUM(TotalAmount) AS Amount FROM Payment GROUP BY 1
注:这种写法的好处是避免重复写转换表达式,缺点是如果后续调整SELECT列的顺序,需要同步修改GROUP BY的序号,不然会出现分组错误。
内容的提问来源于stack exchange,提问作者Maulik Dave
相关产品推荐
相关产品推荐

