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
- Click here查看结果
我有一个针对静态列值的功能性数据透视查询,我想将其转换为动态列值。
查询是:
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
- Click here查看结果