如何在PostgreSQL的GROUP BY分组内计算收入占比?
如何在PostgreSQL中计算分组收入占公司总营收的百分比?
你当前的查询已经完成了按公司、规模分组统计收入的基础需求,要添加各规模收入对应公司总营收的占比,用PostgreSQL的窗口函数就能轻松实现,我帮你修改查询并拆解逻辑:
首先先优化下你原始查询里的冗余部分——外层的GROUP BY是多余的,因为内层CTE已经按公司和segment完成分组了,完全可以去掉。
修改后的完整SQL代码
WITH Test AS ( SELECT id.name AS Company, CASE WHEN li.segment = 'Large' THEN 'Large Cap' WHEN li.segment = 'Medium' THEN 'Mid Cap' WHEN li.segment = 'Small' THEN 'Small Cap' ELSE 'Unknown Cap' -- 替换NULL为明确标识,可选 END AS Size, SUM(ia.amount) AS Revenue, -- 窗口函数:计算当前公司的总营收(按Company分组统计总和) SUM(SUM(ia.amount)) OVER (PARTITION BY id.name) AS Total_Company_Revenue, -- 计算占比并格式化为带百分号的字符串(保留1位小数) ROUND( (SUM(ia.amount)::NUMERIC / SUM(SUM(ia.amount)) OVER (PARTITION BY id.name)) * 100, 1 ) || '%' AS Revenue_Percentage FROM base.company_rev ia JOIN base.company_detail id ON id.company_account_id = ia.company_account_id LEFT JOIN base.product_issued li ON li.product_id = ia.product_id WHERE ia.create_date::date BETWEEN '2018-05-01' AND '2018-05-31' GROUP BY id.name, li.segment ORDER BY 1, 2, 3 ) SELECT Company, Size, Revenue, Revenue_Percentage -- 如果需要展示公司总营收,就把上面的字段换成 Company, Size, Revenue, Total_Company_Revenue, Revenue_Percentage FROM Test ORDER BY Company, Size, Revenue;
关键逻辑说明
- 窗口函数计算公司总营收:
SUM(SUM(ia.amount)) OVER (PARTITION BY id.name)是核心——因为我们已经在GROUP BY里做了一次SUM(ia.amount)统计分组收入,所以窗口函数需要嵌套SUM来计算每个公司的总营收;PARTITION BY id.name表示按公司维度拆分窗口,只统计当前公司的所有分组收入总和。 - 避免整数除法精度丢失:
把SUM(ia.amount)转成NUMERIC类型,是为了防止整数除法导致的精度问题(比如15/25如果用整数计算会得到0,转成NUMERIC后会得到0.6)。 - 百分比格式化:
ROUND(..., 1) || '%'会把计算出的小数转成保留1位小数的百分比字符串,比如60.0%;如果不需要保留小数,把1改成0即可。
如果你不需要展示Total_Company_Revenue字段,直接在最终SELECT里去掉就行,不影响百分比计算。
内容的提问来源于stack exchange,提问作者RTL
相关产品推荐
相关产品推荐

