【问题标题】:SQL Server pivot challengeSQL Server 数据透视挑战
【发布时间】:2015-02-20 14:44:32
【问题描述】:

有两个给定的列 - 前缀和日期时间,例如

PREFIX | DATETIME

ABC    | 2010-01-28 07:11:31.000

DEF    | 2010-02-15 07:11:31.000

DEF    | 2010-01-25 07:11:31.000

我想按年/月和前缀透视数据。 结果应如下所示:

YEAR   | MONTH | ABC | DEF |

2010   | Jan   |  1  |  1  |

2010   | Feb   |  0  |  1  |

也就是说,计算有多少具有相同前缀的对象具有相同的时期(年/月)。

我试过这段代码,但它不起作用,我不知道问题出在哪里。

DECLARE @cols AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(O.OU01) 
                from Test.dbo.Organisation as O
                group by O.OU01
                order by O.OU01
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

set @query = 'SELECT [Year], [month], ' + @cols + ' 
        from 
        (
           SELECT Year(A.Stand) Year,
             Datename(month, A.Stand) [month],
             O.OU01
           FROM Test.dbo.Assets as A
           join Test.dbo.Organisation as O on A.Key = O.Key
        ) x
        pivot 
       (
            Count([O.OU01])
            for O.OU01 in (' + @cols + ')
        ) p '

execute(@query)

【问题讨论】:

  • 你试过什么?除非您的前缀是预定义的(并且数量很少),否则您可能需要使用动态 sql 解决方案,请参阅 *.com/questions/2922797/… 示例
  • 不,前缀不是预定义的。我无法对查询中的前缀进行硬编码
  • @SvenMüller 你是什么意思它不起作用?
  • @bluefeet Msg 207,Level 16,State 1,Line 12 列名“O.OU01”无效。消息 107,级别 15,状态 1,第 13 行列前缀“O”与查询中使用的表名或别名不匹配。
  • @SvenMüller 删除您的数据透视表中的 O. 别名 - 将代码更改为 Count([OU01]) for OU01 in

标签: sql sql-server select pivot unpivot


【解决方案1】:

使用Conditional Aggregate

SELECT Year([DATETIME]) [Year],
       Datename(month, [DATETIME]) [month],
       Count(CASE WHEN PREFIX = 'ABC' THEN 1 END) ABC,
       Count(CASE WHEN PREFIX = 'DEF' THEN 1 END) DEF
FROM   Tablename
GROUP  BY Year([DATETIME]),
          Datename(month, [DATETIME]) 

或使用Pivot

SELECT *
FROM   (SELECT Year([DATETIME])            [Year],
               Datename(month, [DATETIME]) [month],
               PREFIX,
               [DATETIME]
        FROM   tablename) a
       PIVOT (Count([DATETIME])
             FOR PREFIX IN ([ABC],
                            [DEF])) AS P 

SQLFIDDLE DEMO

动态版本:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(PREFIX) 
                    from es
                    group by PREFIX
                    order by PREFIX
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT [Year], [month], ' + @cols + ' 
            from 
            (
               SELECT Year(DATETIMEs)            Year,
                 Datename(month, DATETIMEs) [month],
                 PREFIX
               FROM es
            ) x
            pivot 
            (
                Count([PREFIX])
                for PREFIX in (' + @cols + ')
            ) p '

execute(@query)

Demo

【讨论】:

  • 前缀是动态的,我不能在查询中硬编码
  • @SvenMüller 我为您添加了动态版本。 NoDisplayName,希望您不介意我将其添加到您的答案中。 :)
  • @bluefeet- 我怎么介意先生。感谢动态支点版本 Pivot Guru :) 我从您的回答中学到了支点概念,先生
【解决方案2】:

使用 SQL Server 的 数据透视表

试试这个:

SELECT Year, MonthName, [ABC], [DEF]
FROM (SELECT YEAR(A.DATETIME) AS Year, DATENAME(A.DATETIME,Getdate()) AS MonthName, 
             A.PREFIX  AS Header, A.DATETIME DATA 
        FROM tableA A
     ) AS A 
PIVOT(COUNT(DATA) FOR Header IN ([ABC], [DEF])) AS P

【讨论】:

  • AS MonthName 之后缺少,
  • 前缀是动态的,我不能在查询中硬编码