基于Price列生成分组及子分组排名的SQL查询需求
实现分组与子分组的双重排名思路
没问题,我来帮你理清思路!你需要的其实是利用窗口函数的**分区(PARTITION BY)**特性,结合DENSE_RANK()来同时生成两种排名——整体分组排名和子分组内的排名,完全可以在单条查询里实现。
核心思路拆解
首先,你的需求是基于sum(Price)生成排名,所以第一步得先把每个分组的总价格计算出来;然后通过两次DENSE_RANK()调用,分别生成整体排名和子分组内的排名:
- 整体排名:不对数据做分区,直接按
sum(Price)降序排序,所有分组统一参与排名。 - 子分组排名:通过
PARTITION BY指定子分组维度,让每个子分组内部独立计算排名。
具体SQL示例
假设你的RENTAL表包含:
MainGroup:大分组维度(比如不同业务线)SubGroup:子分组维度(就是你提到的J3、J1这类标识)Price:租金金额
那查询语句可以这么写:
-- 先聚合计算每个子分组的总租金 WITH GroupedTotal AS ( SELECT MainGroup, SubGroup, SUM(Price) AS TotalPrice FROM RENTAL GROUP BY MainGroup, SubGroup ) -- 生成双重排名 SELECT MainGroup, SubGroup, TotalPrice, -- 所有子分组的整体排名(按总租金降序) DENSE_RANK() OVER (ORDER BY TotalPrice DESC) AS OverallRank, -- 每个大分组内的子分组排名(仅在当前MainGroup内排序) DENSE_RANK() OVER (PARTITION BY MainGroup ORDER BY TotalPrice DESC) AS SubGroupRank FROM GroupedTotal ORDER BY OverallRank;
关键部分解释
- CTE聚合层:
GroupedTotal先把每个MainGroup+SubGroup组合的总租金计算出来,避免窗口函数重复计算聚合值,提升效率。 - 整体排名
OverallRank:OVER (ORDER BY TotalPrice DESC)没有指定PARTITION BY,所以所有行都会参与统一排名,就像你说的J3(1600)排第一、J1(1500)排第二这种效果。 - 子分组排名
SubGroupRank:OVER (PARTITION BY MainGroup ...)会把数据按MainGroup拆分,每个MainGroup内部单独按TotalPrice降序生成排名,互不干扰。
灵活调整维度
如果你的子分组不是MainGroup,而是其他维度(比如租赁月份、地区),只需要把PARTITION BY后面的字段换成对应的维度即可。比如按月份做子分组:
DENSE_RANK() OVER (PARTITION BY DATE_TRUNC('month', RentalDate) ORDER BY TotalPrice DESC) AS MonthlySubRank
内容的提问来源于stack exchange,提问作者rAmAnA
相关产品推荐
相关产品推荐

