sql 服务器中的动态数据透视查询

Dynamic pivot query in sql server

我有一个针对静态列值的功能性数据透视查询,我想将其转换为动态列值。

查询是:

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 Invalid column name '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

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

参见示例 here

样本TABLE

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

查询

获取 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