2016-03-04 54 views
0

我很难搞清楚这一点。我检查过类似的帖子,但他们只有一列作为一行旋转。虽然我需要转动具有动态年份列的数据透视SQL表

我有以下查询:

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; 
+0

SQL是不是不适合这种需要,你怎么使用呢?在报告中?通过HTML? –

回答

1

如果您希望在T-SQL中继续使用pivot操作符,那么首先您需要“取消”现有查询,以便拥有Year,Label和Value。虽然T-SQL中有一个unpivot运算符,但我发现使用CROSS APPLY和VALUES要简单得多,速度也一样快(关于Brad Schultz的方法read this article的更多内容),我特别喜欢它,因为我可以轻松地将结果可视化我布置值对的方式。

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中的派生表x。一旦数据被按摩到表单中的支点看起来简单的方法:

 ) x 
     pivot 
     (
      max([x.Value]) 
      for [x.Year] in ([2014],[2015],[2016]) 
     ) p 

为了您@cols我会建议一些简单的像这样:

SELECT DISTINCT 
    QUOTENAME(Year([date])) 
FROM [dbo].[Tickets] 

TIP:如果你需要一种方法对行进行排序,包括在横向施加过,这样的:

 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]可以用来进行枢轴之后。

让整体看起来是这样的:

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;