Sql 如何在以下场景中应用pivot

Sql 如何在以下场景中应用pivot,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我有一张桌子 Name Month Year Count ---------------------------- xxx 12 2012 24 xxx 1 2013 42 xxx 2 2013 23 yyy 12 2012 34 yyy 1 2013 12 yyy 2 2013 54 我想把它转换成下面的格式 Name

我有一张桌子

Name    Month   Year    Count
----------------------------
xxx     12      2012    24
xxx     1       2013    42
xxx     2       2013    23
yyy     12      2012    34
yyy     1       2013    12
yyy     2       2013    54
我想把它转换成下面的格式

Name    Dec-12  Jan-13  Feb-13
--------------------------------
xxx     24      42      23
yyy     34      12      54
如何应用pivot?

尝试以下操作:

WITH CTE
AS
(
  SELECT
    Name, 
    CAST(Month AS VARCHAR(2)) + '-' + CAST(Year AS VARCHAR(4)) AS MonthYear,
    [Count]
  FROM tablename
)
SELECT 
  Name,
  [12-2012] AS 'Dec-12', 
  [1-2013]  AS 'Jan-13', 
  [2-2013]  AS 'Feb-13'
FROM CTE
PIVOT
(  
   MAX([Count])
   FOR MonthYear IN([12-2012], 
                    [1-2013], 
                    [2-2013])
) AS p;
试试这个:

WITH CTE
AS
(
  SELECT
    Name, 
    CAST(Month AS VARCHAR(2)) + '-' + CAST(Year AS VARCHAR(4)) AS MonthYear,
    [Count]
  FROM tablename
)
SELECT 
  Name,
  [12-2012] AS 'Dec-12', 
  [1-2013]  AS 'Jan-13', 
  [2-2013]  AS 'Feb-13'
FROM CTE
PIVOT
(  
   MAX([Count])
   FOR MonthYear IN([12-2012], 
                    [1-2013], 
                    [2-2013])
) AS p;

因为您使用的是SQL Server,所以有几种方法可以将数据从行透视到列

如果您的值是有限的,或者您有已知数量的值,那么您可以使用静态轴硬编码这些值:

select name, [Dec_12], [Jan_13], [Feb_13]
from
(
  select name,
    left(datename(month, dateadd(month, month, 0) -1), 3) +'_'+right(cast(year as varchar(4)), 2) MY,
    [count]
  from yourtable
) src
pivot
(
  sum(count)
  for my in ([Dec_12], [Jan_13], [Feb_13])
) piv;

现在,如果值的数目未知,则需要实现动态SQL来生成结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(my) 
                    from 
                    (
                      select left(datename(month, dateadd(month, month, 0) -1), 3) +'_'+right(cast(year as varchar(4)), 2) my,
                         CAST(
                            CAST(year AS VARCHAR(4)) +
                            RIGHT('0' + CAST(month AS VARCHAR(2)), 2) +
                            '01'
                         AS DATETIME) fulldate
                      from yourtable
                    ) t
                    group by my, fulldate
                    order by fulldate 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT name, ' + @cols + ' 
              from 
             (
                select name,
                  left(datename(month, dateadd(month, month, 0) -1), 3) +''_''+right(cast(year as varchar(4)), 2) MY,
                  [count]
                from yourtable
            ) x
            pivot 
            (
                sum(count)
                for my in (' + @cols + ')
            ) p '

execute(@query)

此版本与静态版本的区别在于,如果您需要未知数量的日期,或者希望此版本在可用时自动更新为新日期,则将返回新数据而不更改代码

两个查询的结果都是:

| NAME | DEC_12 | JAN_13 | FEB_13 |
-----------------------------------
|  xxx |     24 |     42 |     23 |
|  yyy |     34 |     12 |     54 |

因为您使用的是SQL Server,所以有几种方法可以将数据从行透视到列

如果您的值是有限的,或者您有已知数量的值,那么您可以使用静态轴硬编码这些值:

select name, [Dec_12], [Jan_13], [Feb_13]
from
(
  select name,
    left(datename(month, dateadd(month, month, 0) -1), 3) +'_'+right(cast(year as varchar(4)), 2) MY,
    [count]
  from yourtable
) src
pivot
(
  sum(count)
  for my in ([Dec_12], [Jan_13], [Feb_13])
) piv;

现在,如果值的数目未知,则需要实现动态SQL来生成结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(my) 
                    from 
                    (
                      select left(datename(month, dateadd(month, month, 0) -1), 3) +'_'+right(cast(year as varchar(4)), 2) my,
                         CAST(
                            CAST(year AS VARCHAR(4)) +
                            RIGHT('0' + CAST(month AS VARCHAR(2)), 2) +
                            '01'
                         AS DATETIME) fulldate
                      from yourtable
                    ) t
                    group by my, fulldate
                    order by fulldate 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT name, ' + @cols + ' 
              from 
             (
                select name,
                  left(datename(month, dateadd(month, month, 0) -1), 3) +''_''+right(cast(year as varchar(4)), 2) MY,
                  [count]
                from yourtable
            ) x
            pivot 
            (
                sum(count)
                for my in (' + @cols + ')
            ) p '

execute(@query)

此版本与静态版本的区别在于,如果您需要未知数量的日期,或者希望此版本在可用时自动更新为新日期,则将返回新数据而不更改代码

两个查询的结果都是:

| NAME | DEC_12 | JAN_13 | FEB_13 |
-----------------------------------
|  xxx |     24 |     42 |     23 |
|  yyy |     34 |     12 |     54 |

@拉奇查-你什么意思?这是静态透视,但我使用了CTE,只是为了将月份和年份字段格式化为一个字段,然后用不同的别名选择它们。好的。。。我认为这是动态透视,透视列的数量未知。这是一个很好的回答。@Rachcha-你是什么意思?这是静态透视,但我使用了CTE,只是为了将月份和年份字段格式化为一个字段,然后用不同的别名选择它们。好的。。。我认为这是动态透视,透视列的数量未知。这是一个很好的答案。