SQL Server中表动态列查询实现:运营商年度附加费数据转置方案咨询
解决SQL Server中行转列展示运营商月度附加费的问题
刚好碰到过类似的需求,你要把行存储的月度费率数据转成列式的运营商对比表,还要按自然月份排序并格式化百分比,用SQL Server的PIVOT就能搞定,具体实现如下:
完整查询代码
WITH MonthOrder AS ( SELECT MONTH_NAME, MONTH_NUMBER FROM ( VALUES ('January', 1), ('February', 2), ('March', 3), ('April', 4), ('May', 5), ('June', 6), ('July', 7), ('August', 8), ('September', 9), ('October', 10), ('November', 11), ('December', 12) ) AS Months(MONTH_NAME, MONTH_NUMBER) ) SELECT mo.MONTH_NAME AS [Month], -- 格式化DHL费率为两位小数的百分比,无数据则显示0 CASE WHEN dhl_rate IS NULL THEN '0' ELSE FORMAT(dhl_rate, 'N2') + '%' END AS DHL, -- 格式化FedEx费率为两位小数的百分比,无数据则显示0 CASE WHEN fedex_rate IS NULL THEN '0' ELSE FORMAT(fedex_rate, 'N2') + '%' END AS FedEx FROM MonthOrder mo LEFT JOIN ( SELECT MONTH, DHL AS dhl_rate, FedEx AS fedex_rate FROM ( SELECT CARRIER_ID, YEAR, MONTH, RATE FROM YourTableName -- 替换成你的实际表名 WHERE YEAR = 2021 -- 指定要查询的年份 ) AS SourceData PIVOT ( MAX(RATE) FOR CARRIER_ID IN ([DHL], [FedEx]) ) AS PivotTable ) AS PivotedData ON mo.MONTH_NAME = PivotedData.MONTH ORDER BY mo.MONTH_NUMBER;
关键步骤解释
MonthOrder 公用表表达式(CTE):
直接按月份名称排序会是字母顺序(比如April排在August前面),所以我用这个CTE定义了每个月份对应的数字序号,确保最终结果严格按1-12月的自然顺序排列。PIVOT 行转列:
先从你的表中筛选出2021年的数据,然后用PIVOT把CARRIER_ID的不同取值(DHL、FedEx)转成列,用MAX(RATE)是因为每个运营商每个月只有一条数据,MAX和MIN结果完全一致,这里只是借PIVOT的语法实现转列。关联与格式化:
用LEFT JOIN把月份顺序表和转置后的数据关联起来,保证12个月份都会显示,哪怕某个月份没有数据(你的示例里都有,但做个兜底更稳妥)。然后用FORMAT函数把费率转成两位小数的格式,加上百分号,空值的话直接显示0。
小提示
- 记得把代码里的
YourTableName替换成你实际的表名哦。 - 如果以后新增了其他运营商,只需要在
PIVOT的IN子句里加上对应的运营商ID,同时在SELECT部分新增对应的列就行,扩展性很强。
内容的提问来源于stack exchange,提问作者Mr Thanh
相关产品推荐
相关产品推荐

