如何优化SQL语句,筛选各ID的最高聚合销售额分组
优化筛选最高聚合分组的SQL语句
现有Sales表数据
| ID | GroupDescription | Sales |
|---|---|---|
| 1 | Group1 | 2 |
| 1 | Group1 | 15 |
| 1 | Group2 | 3 |
| 1 | Group3 | 2 |
| 1 | Group3 | 2 |
| 1 | Group3 | 2 |
| 2 | Group1 | 2 |
| 2 | Group2 | 5 |
| 2 | Group3 | 3 |
| 2 | Group4 | 12 |
| 2 | Group4 | 2 |
| 2 | Group4 | 2 |
需求与预期输出
为每个ID返回一条记录,包含该ID下销售额最高的分组及该分组的总销售额,预期结果如下:
| ID | GroupDescription | SumSales |
|---|---|---|
| 1 | Group1 | 17 |
| 2 | Group4 | 16 |
现有可运行SQL语句
SELECT * FROM ( SELECT ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID, SumSales DESC) as RowNum, * FROM ( SELECT ID ,GroupDescription ,SUM(Sales) OVER(PARTITION BY ID,GroupDescription) as SumSales FROM Sales ) t1 ) t2 WHERE RowNum = 1
优化方案
方案1:先聚合再排名(推荐)
原SQL内层用窗口函数计算SumSales会保留所有原始行,后续排名处理的数据量较大。先通过GROUP BY聚合得到每个ID+分组的总销售额,再对聚合后的小结果集排名,效率更高且逻辑清晰:
SELECT ID, GroupDescription, SumSales FROM ( SELECT ID, GroupDescription, SUM(Sales) AS SumSales, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY SUM(Sales) DESC) AS RowNum FROM Sales GROUP BY ID, GroupDescription ) t WHERE RowNum = 1
方案2:使用FETCH FIRST WITH TIES(简化语法)
若数据库支持该语法(如SQL Server、PostgreSQL、Oracle等),可直接简化语句,无需嵌套子查询:
SELECT ID, GroupDescription, SUM(Sales) AS SumSales FROM Sales GROUP BY ID, GroupDescription ORDER BY ID, SUM(Sales) DESC FETCH FIRST 1 ROW WITH TIES
注:该语法会返回每个ID组内销售额最高的所有分组(若存在并列第一的情况),与原ROW_NUMBER逻辑一致(仅取一条时效果相同)。
方案3:用CTE提升可读性
通过公共表表达式(CTE)拆分聚合与排名步骤,代码更易维护:
WITH GroupSales AS ( SELECT ID, GroupDescription, SUM(Sales) AS SumSales FROM Sales GROUP BY ID, GroupDescription ), RankedSales AS ( SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY SumSales DESC) AS RowNum FROM GroupSales ) SELECT ID, GroupDescription, SumSales FROM RankedSales WHERE RowNum = 1
内容的提问来源于stack exchange,提问作者user1697891
相关产品推荐
相关产品推荐

