You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Sum聚合分组与Partition by窗口函数的结果差异及正确用法咨询

咱们先直接说结论:你的第二种方法虽然得到了你预期的结果,但写法冗余;而第一种方法完全不符合你的需求,逻辑就错了。下面详细拆解两种方法的差异:

1. 第一种方法:逻辑错误,根本不是按bpm_no汇总

你的第一条SQL:

select a.bpm_no, sum(a.total_amount) from table a group by a.bpm_no, a.total_amount

这里的核心问题出在group by的字段选择上——你同时按bpm_nototal_amount分组,这意味着SQL会把同一个bpm_no下,total_amount值相同的行归为一组,然后统计每组的total_amount总和(其实就是该total_amount本身,因为同一组的total_amount都一样)。

举个实际例子:假设你的表a有这些数据:

bpm_nototal_amount
B001100
B001200
B001100

这条SQL执行后会得到:

bpm_nosum(a.total_amount)
B001200
B001200

这显然不是你想要的“每个bpm_no的total_amount总和”(正确总和应该是400),所以你觉得“丢弃部分值”,本质是这条SQL的分组逻辑完全偏离了你的需求。

2. 第二种方法:结果正确,但写法冗余

你的第二条SQL:

select a.bpm_no, sum(a.total_amount) over (partition by a.bpm_no) from table a group by a.bpm_no,a.total_amount

这条SQL的执行逻辑是分两步的:

  • 第一步执行group by a.bpm_no,a.total_amount,得到和第一条SQL一样的分组结果(每个bpm_no+total_amount的组合行);
  • 第二步用窗口函数sum(...) over (partition by a.bpm_no),对同一个bpm_no下的所有分组行的sum(a.total_amount)值再次求和,最终得到该bpm_no的总总和;
  • 最后每个分组行都会显示这个总总和,所以你能看到所有预期的记录(每个分组行都保留,且对应的总和是正确的)。

还是用刚才的例子,这条SQL会得到:

bpm_nosum(a.total_amount) over (partition by a.bpm_no)
B001400
B001400

结果是对的,但写法绕了弯路——你完全不需要先group by,直接用窗口函数就能得到每个原行对应的bpm_no总和:

select a.bpm_no, sum(a.total_amount) over (partition by a.bpm_no) as total_sum from table a

这样原表有多少行,结果就有多少行,每行的total_sum都是对应bpm_no的总总和,写法更简洁直接。

正确的两种标准写法

根据你的需求,分两种场景:

  • 如果你想要每个bpm_no仅显示一行,对应总总和,用group by的正确写法是:

    select a.bpm_no, sum(a.total_amount) as total_sum from table a group by a.bpm_no
    

    (只按bpm_no分组,去掉total_amount即可)

  • 如果你想要保留原表所有行,同时每行显示对应bpm_no的总总和,用窗口函数的正确写法是:

    select a.bpm_no, a.total_amount, sum(a.total_amount) over (partition by a.bpm_no) as total_sum from table a
    

    (不需要group by,直接给原表加窗口函数)

内容的提问来源于stack exchange,提问作者Md Kamran Azam

火山引擎 最新活动