如何编写SQL实现2015年每季度TOP3高盈利产品统计
解决按季度获取TOP3高盈利产品的问题
嘿,我明白你的需求——要2015年每个季度的TOP3高盈利产品,总共12行数据对吧?你现在的SQL只返回了全局的TOP3,问题出在没有按季度分区来计算排名,而是直接取了全局前3。我来帮你调整一下:
问题分析
你原来的SQL有两个小问题:
GROUP BY里包含了SALES,这会导致同一个季度同一个产品,如果有不同的销售额记录,会被拆分成多条分组结果,而不是按产品聚合所有数据;- 用
rownum <=3是筛选全局的前3行,没有区分季度。
解决方案:用窗口函数实现分区排名
在Oracle里,我们可以用ROW_NUMBER()(或RANK()/DENSE_RANK())窗口函数,按季度分区,然后按盈利降序排名,最后筛选每个季度的前3名。
修改后的SQL如下:
SELECT QUARTER, PRODUCT_NAME, QTY_SOLD, TOTAL_SALES, PROFIT_GENERATED FROM ( SELECT QUARTER, PRODUCT_NAME, SUM(QUANTITY) AS QTY_SOLD, SUM(SALES) AS TOTAL_SALES, -- 对销售额也做聚合,确保按产品+季度汇总 SUM(PROFIT) AS PROFIT_GENERATED, -- 按季度分区,每个季度内按盈利降序排号 ROW_NUMBER() OVER (PARTITION BY QUARTER ORDER BY SUM(PROFIT) DESC) AS RN FROM DELIVERIES_FACT WHERE EXTRACT(YEAR FROM SHIP_DATE) = 2015 GROUP BY QUARTER, PRODUCT_NAME -- 只按季度和产品分组,确保聚合正确 ) WHERE RN <= 3 -- 筛选每个季度的前3名 ORDER BY QUARTER, RN; -- 按季度和排名排序,结果更清晰
关于排名函数的选择
ROW_NUMBER():即使产品盈利相同,也会分配不同的排名(比如两个产品盈利并列第一,会排1和2),确保每个季度刚好3行;RANK():如果有并列的盈利,会给相同的排名,后续排名会跳号(比如两个并列第一,下一个是3),可能导致某季度超过3行;DENSE_RANK():并列盈利会有相同排名,后续排名不跳号(两个并列第一,下一个是2),也可能导致某季度超过3行。
你可以根据实际需求选择合适的排名函数,要是严格要每个季度3行,用ROW_NUMBER()就好。
这样修改后,就能得到2015年每个季度的TOP3高盈利产品,总共12行数据啦!
内容的提问来源于stack exchange,提问作者joas
相关产品推荐
相关产品推荐

