SQL条件计算列需求:按客户、年份及销售类型统计收入
解决按客户统计不同年份、销售类型的收入(行列转换)需求
没问题,针对你的Invoice表统计需求,我们可以用条件聚合的方式来实现行列转换,把年份和销售类型的组合转成结果表中的列。这种方法适用于绝大多数主流SQL数据库(MySQL、SQL Server、PostgreSQL等)。
先回顾下你的原始表结构和数据:
| InvNo | Date | CustName | TypeOfSale | Tax | Grand |
|---|---|---|---|---|---|
| 21 | 2019 | AA | T1 | $1.00 | $10.00 |
| 22 | 2019 | AA | T2 | $2.00 | $20.00 |
| 23 | 2019 | BB | T1 | $1.00 | $10.00 |
| 24 | 2020 | AA | T1 | $1.00 | $10.00 |
| 25 | 2020 | BB | T1 | $1.00 | $10.00 |
| 26 | 2020 | BB | T2 | $2.00 | $20.00 |
你的目标是计算Revenue = Grand - Tax,并按客户统计不同年份、销售类型的收入总和,得到如下结构的结果:
| CustName | Revenue TypeT1 2019 | Revenue TypeT2 2019 | Revenue TypeT1 2020 | Revenue TypeT2 2020 |
|---|---|---|---|---|
| AA | $9.00 | $18.00 | $9.00 | $0.00 |
| BB | $9.00 | $0.00 | $9.00 | $18.00 |
解决方案SQL代码
SELECT CustName, -- 2019年T1类型的收入总和 CONCAT('$', FORMAT(SUM(CASE WHEN Date = 2019 AND TypeOfSale = 'T1' THEN (Grand - Tax) ELSE 0 END), 2)) AS 'Revenue TypeT1 2019', -- 2019年T2类型的收入总和 CONCAT('$', FORMAT(SUM(CASE WHEN Date = 2019 AND TypeOfSale = 'T2' THEN (Grand - Tax) ELSE 0 END), 2)) AS 'Revenue TypeT2 2019', -- 2020年T1类型的收入总和 CONCAT('$', FORMAT(SUM(CASE WHEN Date = 2020 AND TypeOfSale = 'T1' THEN (Grand - Tax) ELSE 0 END), 2)) AS 'Revenue TypeT1 2020', -- 2020年T2类型的收入总和 CONCAT('$', FORMAT(SUM(CASE WHEN Date = 2020 AND TypeOfSale = 'T2' THEN (Grand - Tax) ELSE 0 END), 2)) AS 'Revenue TypeT2 2020' FROM Invoice GROUP BY CustName ORDER BY CustName;
代码解释
核心逻辑:条件聚合
- 用
CASE WHEN语句筛选出符合特定年份和销售类型的记录,计算对应的Grand - Tax,不符合的则返回0 - 用
SUM()函数对筛选后的结果求和,得到该客户对应分组的收入总和
- 用
金额格式化
FORMAT(..., 2)用来确保结果保留两位小数CONCAT('$', ...)用来给金额加上$符号,如果你使用的是SQL Server,可能需要用STR()或者CAST配合CONCAT,比如:CONCAT('$', CAST(SUM(...) AS DECIMAL(10,2)))
分组与排序
GROUP BY CustName确保我们按客户进行统计ORDER BY CustName让结果按客户名称排序,更清晰
注意事项
- 如果你的
Date字段是日期类型(不是单纯的年份数字),需要用年份提取函数,比如YEAR(Date) = 2019来替代Date = 2019 - 不同数据库的格式化函数略有差异,比如PostgreSQL用
TO_CHAR,可以根据你的数据库类型调整格式化部分的代码
内容的提问来源于stack exchange,提问作者Hamid Reza
相关产品推荐
相关产品推荐

