在SQL Server 2012中用单查询获取列的最值、均值及最后值
解决SQL Server 2012中分组同时获取最大/最小/平均及最后值的问题
我明白你的需求:按Month和Acc分组,在同一查询中得到每组的最小余额、平均余额、最大余额,以及该分组里的最后一条余额(从示例数据看,应该是按SN递增顺序的最后一条,也就是每组中SN最大的那条记录的Bal)。
你之前遇到的问题是:直接在聚合查询里用LAST_VALUE窗口函数会导致要么返回所有记录(因为GROUP BY里加了Bal),要么报错(Bal不在聚合函数或GROUP BY中),这是因为窗口函数和聚合函数的工作逻辑不一样——窗口函数是对行集进行逐行计算,而聚合函数是将行集合并为分组后的单行结果。
下面给你几种可行的解决方案:
方法一:子查询获取每组最大SN,再关联聚合
这种方法先找到每个(Month, Acc)分组里最大的SN(以此确定最后一条记录),再和原表关联,同时完成聚合计算:
SELECT t.[Month], t.[Acc], MIN(t.Bal) AS MinBal, AVG(t.Bal) AS AvgBal, MAX(t.Bal) AS MaxBal, last_rec.Bal AS LastBal FROM MyTable t INNER JOIN ( -- 先获取每个分组的最大SN SELECT [Month], [Acc], MAX(SN) AS MaxSN FROM MyTable GROUP BY [Month], [Acc] ) last_rec ON t.[Month] = last_rec.[Month] AND t.[Acc] = last_rec.[Acc] AND t.SN = last_rec.MaxSN GROUP BY t.[Month], t.[Acc], last_rec.Bal
方法二:用CTE+ROW_NUMBER标记最后一条记录
先给每个分组内的记录按SN倒序排名,标记出最后一条(排名为1),再结合聚合统计:
WITH RankedRecords AS ( SELECT [Month], [Acc], Bal, -- 每个分组内按SN倒序排名,最后一条的rn=1 ROW_NUMBER() OVER (PARTITION BY [Month], [Acc] ORDER BY SN DESC) AS rn FROM MyTable ), AggregatedStats AS ( -- 先计算分组的聚合值 SELECT [Month], [Acc], MIN(Bal) AS MinBal, AVG(Bal) AS AvgBal, MAX(Bal) AS MaxBal FROM RankedRecords GROUP BY [Month], [Acc] ) -- 关联获取最后一条的Bal SELECT agg.[Month], agg.[Acc], agg.MinBal, agg.AvgBal, agg.MaxBal, rr.Bal AS LastBal FROM AggregatedStats agg INNER JOIN RankedRecords rr ON agg.[Month] = rr.[Month] AND agg.[Acc] = rr.[Acc] AND rr.rn = 1
为什么你之前的写法有问题?
- 当你在
GROUP BY里加上Bal时,SQL Server会把每个不同的Bal值都作为单独的分组,所以返回的是每条记录的结果,而不是按Month和Acc聚合的结果。 - 如果不加
Bal在GROUP BY里,SELECT中的Bal既不在聚合函数里,也不在GROUP BY子句中,违反了SQL Server的查询规则,所以会报错。
内容的提问来源于stack exchange,提问作者KoolKabin
相关产品推荐
相关产品推荐

