SQL Server嵌套查询/CTE问题:求盈利州利润累计占比
按州利润累计占比的SQL解决方案
原代码存在的问题
- 外层
GROUP BY state, sum_of_profit属于冗余操作,子查询已按州分组,每个州仅返回一条利润汇总数据 sum(sum_of_profit)因外层分组限制,计算的是单个州自身的利润总和,导致perc字段结果恒为100%,无法得到正确占比- 未实现累计占比逻辑,仅尝试计算单个州的利润占比
修正后的SQL代码(通用窗口函数版本)
适用于支持窗口函数的SQL方言(PostgreSQL、MySQL 8.0+、SQL Server等):
WITH profit_by_state AS ( SELECT state, SUM(profit) AS sum_of_profit FROM superstore GROUP BY state HAVING SUM(profit) > 0 -- 排除亏损州 ) SELECT state, sum_of_profit, -- 单个州利润占总盈利的比例(保留两位小数) ROUND(sum_of_profit / SUM(sum_of_profit) OVER() * 100, 2) AS individual_percentage, -- 从利润最高州开始的累计占比(保留两位小数) ROUND(SUM(sum_of_profit) OVER(ORDER BY sum_of_profit DESC) / SUM(sum_of_profit) OVER() * 100, 2) AS cumulative_percentage FROM profit_by_state ORDER BY sum_of_profit DESC;
代码说明
- CTE
profit_by_state:按州分组计算利润总和,过滤掉利润≤0的亏损州 - 全局总盈利计算:
SUM(sum_of_profit) OVER()无分区无排序,返回所有盈利州的总利润,作为占比计算的分母 - 累计占比实现:
SUM(sum_of_profit) OVER(ORDER BY sum_of_profit DESC)按利润从高到低排序,计算累计利润,再除以总盈利得到累计占比 - ROUND函数:将百分比结果保留两位小数,提升可读性
兼容低版本SQL的方案(无窗口函数)
如果使用不支持窗口函数的旧版SQL(如MySQL 5.x),可以用子查询计算总盈利:
SELECT p.state, p.sum_of_profit, ROUND(p.sum_of_profit / t.total_profit * 100, 2) AS individual_percentage, ROUND((SELECT SUM(sum_of_profit) FROM profit_by_state WHERE sum_of_profit >= p.sum_of_profit) / t.total_profit * 100, 2) AS cumulative_percentage FROM ( SELECT state, SUM(profit) AS sum_of_profit FROM superstore GROUP BY state HAVING SUM(profit) > 0 ) p, ( SELECT SUM(sum_of_profit) AS total_profit FROM ( SELECT SUM(profit) AS sum_of_profit FROM superstore GROUP BY state HAVING SUM(profit) > 0 ) temp ) t ORDER BY p.sum_of_profit DESC;
内容的提问来源于stack exchange,提问作者Michał
相关产品推荐
相关产品推荐

