【问题标题】:SQL How to PIVOT table using common table expression and dynamic SQLSQL 如何使用公用表表达式和动态 SQL 透视表
【发布时间】:2012-12-06 22:37:44
【问题描述】:

我有这个按月分组搜索的 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

结果如下所示:

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

我正在尝试弄清楚如何使用PIVOT 来实现这一目标:

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

谁能告诉我怎么做?

【问题讨论】:

    标签: sql sql-server tsql pivot common-table-expression


    【解决方案1】:

    你可以这样使用:

    ; 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
    

    SQL Fiddle with Demo

    如果你有未知的月数要转换,那么你可以使用类似这样的动态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)
    

    SQL Fiddle with Demo

    【讨论】:

    • 是的,就是这样,但我可以使用 CTE 而不是写入月份值(9、10、11 等)吗?我正在准备一份最近 3 个月的报告
    • 如果您不知道月份的值,那​​么您将不得不使用动态 sql 来执行此操作
    • 在你的 SQL Fiddle 中,为什么最后是 9(九月)?因为它被视为字符串?
    • @greener 现在应该修复了。
    • 谢谢。这正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 2010-09-26
    • 2010-12-28
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多