sql server中的动态数据透视查询

时间:2015-01-19 08:58:22

标签: sql sql-server dynamic-sql

我对静态列值有一个正常运行的数据透视查询,我希望将其转换为动态列值。

查询是:

with a as (

select  request_id, dateadd(month,datediff(month,0,logged_datetime),0) as 'Month'
,dateadd(month,datediff(month,0,logged_datetime),0) as 'Year'

 from requests

 )


 select  * from (

 select datepart(m,a.Month) as 'months',datepart(YEAR,a.Year) as 'years',a.request_id

  from a  ) ps

 pivot (

 count(request_id) for [years] in ([2008],[2009],[2010],[2011],[2012],[2013],[2014],[2015])
 ) as pvt
 order by months

对于下面写的动态查询,我收到错误,如

  

Msg 207,Level 16,State 1,Line 5无效的列名称'2010'。 :

select distinct datepart(year,dateadd(month,datediff(month,0,logged_datetime),0)) as 'Yearz'

into #t

FROM requests

DECLARE @Dynamic AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)

SELECT @ColumnName= ISNULL(@ColumnName + ',','') 
       + QUOTENAME(Yearz)
FROM (SELECT * from #t) AS Yea


SET @Dynamic = 
  N'

 select  * from (

 select datepart(m,dateadd(month,datediff(month,0,logged_datetime),0)) as months,' + @ColumnName + ',request_id

  from requests ) ps

 pivot (

 count(request_id) for [Years] in (' + @ColumnName + ')
 ) as pvt
 order by months
'

EXEC sp_executesql @Dynamic

2 个答案:

答案 0 :(得分:0)

我认为您需要使用QUOTENAME函数包装动态列名:

参见示例here

答案 1 :(得分:0)

样本表

SELECT * INTO #REQUESTS
FROM
(
    SELECT 1 request_id, '2012-06-01' logged_datetime
    UNION ALL
    SELECT 2 request_id,  '2012-05-01'
    UNION ALL
    SELECT 11 request_id, '2012-06-01' 
    UNION ALL
    SELECT 12 request_id,  '2012-05-01'
    UNION ALL
    SELECT 3 request_id,  '2012-07-01' 
    UNION ALL
    SELECT 4 request_id,  '2013-09-01' 
    UNION ALL
    SELECT 5 request_id,  '2013-10-01' 
    UNION ALL
    SELECT 6 request_id, '2014-01-01' 
    UNION ALL
    SELECT 7 request_id,  '2014-02-01' 
    UNION ALL
    SELECT 8 request_id, '2014-03-01' 
    UNION ALL
    SELECT 9 request_id,  '2014-05-01' 
    UNION ALL
    SELECT 10 request_id,  '2015-11-01' 
)TAB

<强> QUERY

获取years的列,并按数字顺序对其进行排序

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + CAST([YEAR] AS VARCHAR(4)) + ']',  '[' + CAST([YEAR] AS VARCHAR(4)) + ']')
               FROM    (SELECT DISTINCT YEAR(dateadd(month,datediff(month,0,logged_datetime),0)) [YEAR] FROM #REQUESTS) PV  
               ORDER BY CAST([YEAR] AS INT)

现在转动查询

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT * FROM 
             ( 
                 -- We will get the count for a year and number of request_id in that month here as CNT column
                 select DISTINCT datepart(m,a.Month) as ''months'',datepart(YEAR,a.Year) as ''years'',
                COUNT(*) OVER(PARTITION BY datepart(YEAR,a.Year),datepart(m,a.Month)) CNT
                 from
                 (
                    select  request_id, dateadd(month,datediff(month,0,logged_datetime),0) as ''Month''
                    ,dateadd(month,datediff(month,0,logged_datetime),0) as ''Year''
                     from #requests
                 )a 
             ) x
             PIVOT 
             (
                 MIN(CNT)
                 FOR years IN (' + @cols + ')
            ) p
            ORDER BY MONTHS;' 

EXEC SP_EXECUTESQL @query