SQL PIVOT 可以做这样的转换吗?
Posted
技术标签:
【中文标题】SQL PIVOT 可以做这样的转换吗?【英文标题】:Can SQL PIVOT do such transformation? 【发布时间】:2016-12-07 09:10:04 【问题描述】:我的数据看起来像
+-------+-------+-------+------+
| Group | Count | Month | Year |
+-------+-------+-------+------+
| A | 102 | Jan | 2015 |
| B | 20 | Jan | 2016 |
| C | 30 | Feb | 2015 |
| A | 10 | Jan | 2016 |
| C | 20 | Feb | 2016 |
+-------+-------+-------+------+
我想要这样的输出
+-------+-------+------+-------+
| Group | Month | 2015 | 2016 |
+-------+-------+------+-------+
| A | Jan | 102| 10 |
| B | Jan | 20 | 0 |
| C | Feb | 30 | 20 |
+-------+-------+------+-------+
我尝试使用 PIVOT,但我不确定它是否会显示我想要的结果。
下面的查询是我的一次糟糕的尝试(不起作用)-
SELECT 'Total' AS Total,
[2015], [2016]
FROM
(SELECT DATENAME(YEAR,[mydate]) as Y, Datename(month,[mydate]) as M
FROM incidents) AS SourceTable
PIVOT
(
count(DATENAME(YEAR,[mydate]))
FOR DATENAME(YEAR,[mydate]) IN (2015,2016)
) AS PivotTable;
我的日期列采用这种格式2016-01-20 03:00:11.000
。我使用MONTH()
和DATENAME
函数来提取月份编号和名称。
【问题讨论】:
在您提议的结果中,2015 年的组A
不应该是 102
和 2016 年的 10
?
添加您需要的所有列以选择您的sourcetable
列表。在此子选择之外,您无需再次获取 datename
- 您已经有 Y 和 M 列。
@IvanSivak 是的。现已更正。
【参考方案1】:
我认为这是你需要的:
WITH Src AS
(
SELECT * FROM (VALUES
('A',102, 'Jan', 2015),
('B', 20, 'Jan', 2016),
('C', 30, 'Feb', 2015),
('A', 10, 'Jan', 2016),
('C', 20, 'Feb', 2016)) T([Group], Count, Month, Year)
)
SELECT [Group],Month,ISNULL([2015],0) [2015],ISNULL([2016],0) [2016] FROM Src
PIVOT
(SUM(Count) FOR Year IN ([2015], [2016])) AS Pvt
ORDER BY [Group],Month
【讨论】:
工作就像一个魅力!谢谢。【参考方案2】:真的不需要实际的pivot
操作。
select
"Group", "Month",
case when "Year" = 2015 then sum("Count") end as "2015",
case when "Year" = 2016 then sum("Count") end as "2016"
from incidents
group by "Group", "Month"
sum()
聚合只是包含此示例数据的虚拟函数。甚至可以是min()
或max()
或avg()
。
【讨论】:
以上是关于SQL PIVOT 可以做这样的转换吗?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 使用 Pivot 和 UnPivot 实现行列转换