SQL自连接统计近2天金额总和出现重复行且无法用distinct如何解决
问题根因
查询结果重复、求和值偏大来自三个逻辑漏洞:
- 自连接仅匹配了ID字段,同ID下同一日期存在多条不同交易记录时会产生笛卡尔积,关联后行数成倍放大,sum计算时会重复累加金额
- 日期过滤条件写在
where子句中,会过滤掉左表未匹配到右表的行,导致left join退化为inner join - 日期判断规则
a."Date" - b."Date" < 2没有做非负限制,会把统计日期之后的交易记录也纳入关联,不符合"统计过去2天金额"的业务要求
修正方案
不需要使用distinct,调整关联逻辑即可解决:
- 先把左表的统计粒度收敛到
ID+Date(即最终输出的粒度),避免同日期下多条交易作为基准行触发笛卡尔积 - 把所有日期过滤条件移到
left join的on子句中,补全日期范围上下限,仅关联同一ID下、日期落在统计日及统计日前2天区间内的交易记录
修正后的SQL代码如下:
select a."ID", a."Date", sum(b."Amount") as past_2days_total from ( -- 收敛左表粒度到ID+Date,消除笛卡尔积来源 select "ID", "Date" from data group by "ID", "Date" ) a left join data b on a."ID" = b."ID" -- 限定b表日期范围:统计日前2天到统计日当天 and b."Date" <= a."Date" and a."Date" - b."Date" < 2 group by a."ID", a."Date" order by a."ID", a."Date" asc;
不同数据库的日期计算语法略有差异:如果是PostgreSQL、Oracle这类数据库,日期差值计算需要搭配interval语法使用,按实际数据库语法调整日期判断部分即可,核心逻辑不变。
基于给出的样例数据,该查询的输出结果为:
| ID | Date | past_2days_total |
|---|---|---|
| 1 | 1/01/2022 | 1301 |
| 1 | 2/01/2022 | 2286 |
| 1 | 1/03/2022 | 9442 |
计算结果完全符合预期,没有重复行。
内容的提问来源于stack exchange,提问作者Cari Cambiante
相关产品推荐
相关产品推荐

