SQL求助:如何基于两行数据计算各列占比并生成目标表格
计算每行数据在对应列中的百分比(SQL实现)
现有table1表格数据:
| Year | Col1 | Col2 |
|---|---|---|
| Year 1 | 61 | 67 |
| Year 2 | 56 | 75 |
需要生成以下格式的百分比结果:
| Year | Col1 | Col2 |
|---|---|---|
| Year 1 % | 52.14% | 47.18% |
| Year 2 % | 47.86% | 52.81% |
当前使用的SQL语句无法得到目标结果:
SELECT Year1 ,[Col1], ([Col1] * 100) / (SELECT ISNULL(SUM([Col1]),0) FROM table1) AS Percentage FROM table1 UNION ALL SELECT Year2 ,Col2, ([Col2] * 100) / (SELECT ISNULL(SUM([Col2]),0) FROM table1) AS Percentage FROM table1
问题分析
原SQL的问题在于用UNION ALL将列数据拆分为行输出,破坏了原表格的列结构;同时列名引用错误(Year1、Year2并非有效列名),且整数除法会直接丢失小数精度。
正确实现方案
方案1:子查询计算列总和(通用SQL)
SELECT CONCAT(Year, ' %') AS Year, ROUND((Col1 * 100.0) / (SELECT SUM(Col1) FROM table1), 2) || '%' AS Col1, ROUND((Col2 * 100.0) / (SELECT SUM(Col2) FROM table1), 2) || '%' AS Col2 FROM table1;
方案2:窗口函数(高效,适配多数现代数据库)
SELECT CONCAT(Year, ' %') AS Year, ROUND((Col1 * 100.0) / SUM(Col1) OVER(), 2) || '%' AS Col1, ROUND((Col2 * 100.0) / SUM(Col2) OVER(), 2) || '%' AS Col2 FROM table1;
细节说明
- 使用
100.0而非100是为了触发浮点运算,避免整数除法导致的精度丢失 ROUND(..., 2)用于保留两位小数,不同数据库的格式化语法略有差异:- SQL Server 可替换为
FORMAT((Col1*100.0)/SUM(Col1) OVER(), 'N2') + '%' - MySQL 可替换为
CONCAT(ROUND((Col1*100.0)/SUM(Col1), 2), '%')
- SQL Server 可替换为
CONCAT(Year, ' %')用于生成带百分号的年份标题
内容的提问来源于stack exchange,提问作者jk1844
相关产品推荐
相关产品推荐

