Pivot SQL table 与动态年份列
Pivot SQL table with dynamic year columns
我无法弄清楚这一点。我检查过类似的帖子,但它们只有一列作为一行旋转。虽然我需要调整
我有以下查询:
SELECT
Year([Date]) as Year
,SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as 'Per Cap'
FROM [dbo].[Tickets]
group by [Date]
哪个给我这个结果:
Year Drop TicketsDistributed TicketsSold GrossTickets Per Cap
2016 222 100 5000 4000.00 0.800000
2015 222 110 5000 4000.00 0.900000
2014 222 120 5000 4000.00 1.00000
我想要以下内容:
2016 2015 2014
Drop 222 222 222
TicketsDistributed 100 110 120
TicketsSold 5000 5000 5000
GrossTickets 4000 4000 4000
Per Cap 0.8 0.9 1
根据建议的答案,这是我目前的答案,但它不起作用
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Year(Date))
from [dbo].[SpringTrainings] t
cross apply
(
select SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as PerCap
FROM [dbo].[SpringTrainings]
) c ([Drop],[TicketsDistributed],[TicketsSold],[GrossTickets],PerCap)
group by Year(Date)
order by Year(Date)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT [Drop],[TicketsDistributed],[TicketsSold],[GrossTickets],PerCap,' + @cols + '
from
(
select SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as PerCap
FROM [dbo].[SpringTrainings]
) x
pivot
(
max(Year([Date]))
for Year([Date]) in (' + @cols + ')
) p '
execute sp_executesql @query;
如果您希望在 T-SQL 中继续使用数据透视运算符,那么您首先需要 "unpivot" 现有查询,以便获得年份、标签和值。虽然 T-SQL 中有一个 unpivot 运算符,但我个人发现使用 CROSS APPLY 和 VALUES 更简单并且同样快(更多关于他的方法 read this article by Brad Schultz),我特别喜欢它因为我可以通过布置值对的方式轻松地将结果可视化。
SELECT
d.Year
, a.label
, a.value
FROM (
SELECT
YEAR([Date]) AS [Year]
, SUM([Drop]) AS [Drop]
, SUM([TicketsDistributed]) AS [TicketsDistributed]
, SUM([TicketsSold]) AS [TicketsSold]
, SUM([GrossTickets]) AS [GrossTickets]
, SUM([GrossTickets]) / SUM(TicketsSold) AS [PerCap]
FROM [dbo].[Tickets]
GROUP BY
[Year]
) AS t
CROSS APPLY ( /* now transform into 5 rows per year but just 1 value column */
VALUES
('Drop',t.Drop)
, ('TicketsDistributed',t.TicketsDistributed)
, ('TicketsSold',t.TicketsSold)
, ('GrossTickets',t.GrossTickets)
, ('PerCap',t.PerCap)
) AS a (label, value)
该查询(以上)替换了动态 SQL 中派生的 table x
。一旦数据被处理成那种形式,枢轴看起来就简单多了:
) x
pivot
(
max([x.Value])
for [x.Year] in ([2014],[2015],[2016])
) p
对于你的@cols,我会建议像这样简单的东西:
SELECT DISTINCT
QUOTENAME(Year([date]))
FROM [dbo].[Tickets]
提示:如果您需要一种对行进行排序的方法,请将其也包括在交叉应用中,如下所示:
CROSS APPLY ( /* now transform into 5 rows per year but just 1 value column */
VALUES
(1, 'Drop',t.Drop)
, (2, 'TicketsDistributed',t.TicketsDistributed)
, (3, 'TicketsSold',t.TicketsSold)
, (4, 'GrossTickets',t.GrossTickets)
, (5, 'PerCap',t.PerCap)
) AS a (row_order, label, value)
然后那个[row_order]可以在执行pivot后使用
所以整体看起来像这样:
DECLARE @cols AS nvarchar(max)
, @query AS nvarchar(max)
SELECT @cols = STUFF((
SELECT DISTINCT
',' + QUOTENAME(YEAR([date]))
FROM [dbo].[Tickets]
FOR xml PATH (''), TYPE
)
.value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
SET @query = 'SELECT [Year], [Label], '
+ @cols
+ ' FROM (
SELECT
d.Year
, a.label
, a.value
FROM (
SELECT
YEAR([Date]) AS [Year]
, SUM([Drop]) AS [Drop]
, SUM([TicketsDistributed]) AS [TicketsDistributed]
, SUM([TicketsSold]) AS [TicketsSold]
, SUM([GrossTickets]) AS [GrossTickets]
, SUM([GrossTickets]) / SUM(TicketsSold) AS [PerCap]
FROM [dbo].[Tickets]
GROUP BY
[Year]
) AS d
CROSS APPLY (
VALUES
(1,''Drop'',t.Drop)
, (2,''TicketsDistributed'',t.TicketsDistributed)
, (3,''TicketsSold'',t.TicketsSold)
, (4,''GrossTickets'',t.GrossTickets)
, (5,''PerCap'',t.PerCap)
) AS a (row_order,label,value)
) x
pivot
(
max([x.Value])
for [x.Year] in (' + @cols + ')
) p
ORDER BY [row_order]'
EXECUTE sp_executesql @query;
我无法弄清楚这一点。我检查过类似的帖子,但它们只有一列作为一行旋转。虽然我需要调整
我有以下查询:
SELECT
Year([Date]) as Year
,SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as 'Per Cap'
FROM [dbo].[Tickets]
group by [Date]
哪个给我这个结果:
Year Drop TicketsDistributed TicketsSold GrossTickets Per Cap
2016 222 100 5000 4000.00 0.800000
2015 222 110 5000 4000.00 0.900000
2014 222 120 5000 4000.00 1.00000
我想要以下内容:
2016 2015 2014
Drop 222 222 222
TicketsDistributed 100 110 120
TicketsSold 5000 5000 5000
GrossTickets 4000 4000 4000
Per Cap 0.8 0.9 1
根据建议的答案,这是我目前的答案,但它不起作用
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Year(Date))
from [dbo].[SpringTrainings] t
cross apply
(
select SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as PerCap
FROM [dbo].[SpringTrainings]
) c ([Drop],[TicketsDistributed],[TicketsSold],[GrossTickets],PerCap)
group by Year(Date)
order by Year(Date)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT [Drop],[TicketsDistributed],[TicketsSold],[GrossTickets],PerCap,' + @cols + '
from
(
select SUM([Drop]) as [Drop]
,SUM([TicketsDistributed]) as [TicketsDistributed]
,SUM([TicketsSold]) as [TicketsSold]
,SUM([GrossTickets]) as [GrossTickets]
,SUM([GrossTickets])/SUM(TicketsSold) as PerCap
FROM [dbo].[SpringTrainings]
) x
pivot
(
max(Year([Date]))
for Year([Date]) in (' + @cols + ')
) p '
execute sp_executesql @query;
如果您希望在 T-SQL 中继续使用数据透视运算符,那么您首先需要 "unpivot" 现有查询,以便获得年份、标签和值。虽然 T-SQL 中有一个 unpivot 运算符,但我个人发现使用 CROSS APPLY 和 VALUES 更简单并且同样快(更多关于他的方法 read this article by Brad Schultz),我特别喜欢它因为我可以通过布置值对的方式轻松地将结果可视化。
SELECT
d.Year
, a.label
, a.value
FROM (
SELECT
YEAR([Date]) AS [Year]
, SUM([Drop]) AS [Drop]
, SUM([TicketsDistributed]) AS [TicketsDistributed]
, SUM([TicketsSold]) AS [TicketsSold]
, SUM([GrossTickets]) AS [GrossTickets]
, SUM([GrossTickets]) / SUM(TicketsSold) AS [PerCap]
FROM [dbo].[Tickets]
GROUP BY
[Year]
) AS t
CROSS APPLY ( /* now transform into 5 rows per year but just 1 value column */
VALUES
('Drop',t.Drop)
, ('TicketsDistributed',t.TicketsDistributed)
, ('TicketsSold',t.TicketsSold)
, ('GrossTickets',t.GrossTickets)
, ('PerCap',t.PerCap)
) AS a (label, value)
该查询(以上)替换了动态 SQL 中派生的 table x
。一旦数据被处理成那种形式,枢轴看起来就简单多了:
) x
pivot
(
max([x.Value])
for [x.Year] in ([2014],[2015],[2016])
) p
对于你的@cols,我会建议像这样简单的东西:
SELECT DISTINCT
QUOTENAME(Year([date]))
FROM [dbo].[Tickets]
提示:如果您需要一种对行进行排序的方法,请将其也包括在交叉应用中,如下所示:
CROSS APPLY ( /* now transform into 5 rows per year but just 1 value column */
VALUES
(1, 'Drop',t.Drop)
, (2, 'TicketsDistributed',t.TicketsDistributed)
, (3, 'TicketsSold',t.TicketsSold)
, (4, 'GrossTickets',t.GrossTickets)
, (5, 'PerCap',t.PerCap)
) AS a (row_order, label, value)
然后那个[row_order]可以在执行pivot后使用
所以整体看起来像这样:
DECLARE @cols AS nvarchar(max)
, @query AS nvarchar(max)
SELECT @cols = STUFF((
SELECT DISTINCT
',' + QUOTENAME(YEAR([date]))
FROM [dbo].[Tickets]
FOR xml PATH (''), TYPE
)
.value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
SET @query = 'SELECT [Year], [Label], '
+ @cols
+ ' FROM (
SELECT
d.Year
, a.label
, a.value
FROM (
SELECT
YEAR([Date]) AS [Year]
, SUM([Drop]) AS [Drop]
, SUM([TicketsDistributed]) AS [TicketsDistributed]
, SUM([TicketsSold]) AS [TicketsSold]
, SUM([GrossTickets]) AS [GrossTickets]
, SUM([GrossTickets]) / SUM(TicketsSold) AS [PerCap]
FROM [dbo].[Tickets]
GROUP BY
[Year]
) AS d
CROSS APPLY (
VALUES
(1,''Drop'',t.Drop)
, (2,''TicketsDistributed'',t.TicketsDistributed)
, (3,''TicketsSold'',t.TicketsSold)
, (4,''GrossTickets'',t.GrossTickets)
, (5,''PerCap'',t.PerCap)
) AS a (row_order,label,value)
) x
pivot
(
max([x.Value])
for [x.Year] in (' + @cols + ')
) p
ORDER BY [row_order]'
EXECUTE sp_executesql @query;