简体   繁体   English

SQL如何使用公用表表达式和动态SQL来创建PIVOT表

[英]SQL How to PIVOT table using common table expression and dynamic SQL

I have this SQL query which groups searches by month: 我有此SQL查询按月分组搜索:

; with Mth (st, nd) as (
    select DATEADD (M, datediff (m, 0,'2012-09-01'), 0),
            DATEADD (M, DATEDIFF (m, 0, '2012-09-01') + 1, 0)  
    union all
    select DATEADD (m, 1, st),
            DATEADD (m, 1, nd)
    from Mth
    where nd <= DATEADD (m, datediff (m, 0, getdate()), 0)
)
select MONTH(Mth.st) Month,
    COUNT(S.QRY_ID) Searches
FROM Mth
LEFT JOIN SEARCHES S
on Mth.st <= S.CREATED
and Mth.nd > S.CREATED
GROUP BY YEAR(Mth.st), MONTH(Mth.st)
ORDER BY 1,2

The result appears like this: 结果显示如下:

 Month  |  Searches
---------------------
   9    |    21
   10   |    32
   11   |    18

I'm trying to figure out how to use PIVOT to achieve this: 我试图弄清楚如何使用PIVOT实现此目的:

  9   |   10    |   11
-----------------------
  21  |   32    |   18

Could anyone please explain to me how to do it? 谁能告诉我怎么做?

You can use something like this: 您可以使用如下形式:

; with Mth (st, nd) as (
    select DATEADD (M, datediff (m, 0,'2012-09-01'), 0),
            DATEADD (M, DATEDIFF (m, 0, '2012-09-01') + 1, 0)  
    union all
    select DATEADD (m, 1, st),
            DATEADD (m, 1, nd)
    from Mth
    where nd <= DATEADD (m, datediff (m, 0, getdate()), 0)
)
select *
from
(
  select MONTH(Mth.st) Month,
      COUNT(S.QRY_ID) Searches
  FROM Mth
  LEFT JOIN SEARCHES S
    on Mth.st <= S.CREATED
    and Mth.nd > S.CREATED
  GROUP BY YEAR(Mth.st), MONTH(Mth.st)
) src
pivot
(
  sum(searches)
  for month in ([9], [10], [11])
) piv

See SQL Fiddle with Demo 参见带有演示的SQL Fiddle

If you have an unknown number of months to transform, then you can use dynamic sql similar to this: 如果您要转换的月份数未知,则可以使用类似于以下内容的动态sql:

; with Mth (st, nd) as (
    select DATEADD (M, datediff (m, 0,'2012-09-01'), 0),
            DATEADD (M, DATEDIFF (m, 0, '2012-09-01') + 1, 0)  
    union all
    select DATEADD (m, 1, st),
            DATEADD (m, 1, nd)
    from Mth
    where nd <= DATEADD (m, datediff (m, 0, getdate()), 0)
)
select *
into #dates
from Mth

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

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

set @query = ' with Mth (st, nd) as (
                select DATEADD (M, datediff (m, 0,''2012-09-01''), 0),
                        DATEADD (M, DATEDIFF (m, 0, ''2012-09-01'') + 1, 0)  
                union all
                select DATEADD (m, 1, st),
                        DATEADD (m, 1, nd)
                from Mth
                where nd <= DATEADD (m, datediff (m, 0, getdate()), 0)
            )
            select *
            from
            (
              select MONTH(Mth.st) Month,
                  COUNT(S.QRY_ID) Searches
              FROM Mth
              LEFT JOIN SEARCHES S
                on Mth.st <= S.CREATED
                and Mth.nd > S.CREATED
              GROUP BY YEAR(Mth.st), MONTH(Mth.st)
            ) src
            pivot
            (
              sum(searches)
              for month in ('+@cols+')
            ) piv'

execute(@query)

See SQL Fiddle with Demo 参见带有演示的SQL Fiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM