动态将列名传递给UNPIVOT


10

我有一个包含以下数据的表

First         Second        Third         Fourth        Fifth         Sixth
2013-08-20    2013-08-21    2013-08-22    2013-08-23    2013-08-24    2013-08-25

并使用 UNPIVOT

SELECT Data
    ,DATENAME(DW, Data) AS DayName
FROM Cal
UNPIVOT(Data FOR D IN (
            First,
            Second,
            Third,
            Fourth,
            Fifth,
            Sixth  )) AS unpvt

我得到以下结果

Data        DayName
2013-08-20  Tuesday
2013-08-21  Wednesday
2013-08-22  Thursday
2013-08-23  Friday
2013-08-24  Saturday
2013-08-25  Sunday

现在我的问题是我们可以动态地将列名传递给,UNPIVOT以便当表中的列增加时,我们不必更改该语句。

Answers:


14

如果您需要取消透视的列数未知,那么您将不得不考虑实现动态SQL。

您可以sys.columns用来获取表中所有列的名称cal。如果使用以下查询,则将获取表中所有列的列表:

select C.name
from sys.columns c
where c.object_id = OBJECT_ID('dbo.cal') 

现在,您可以使用此查询以及FOR XML PATH创建逗号分隔的名称列表,以将这些名称连接到要执行的字符串:

select @colsUnpivot 
  = stuff((select ','+quotename(C.name)
           FROM sys.columns c
           WHERE c.object_id = OBJECT_ID('dbo.cal') 
           for xml path('')), 1, 1, '')

最后,您将获得此列表并将其放入要执行的查询字符串中,这样完整的查询将如下所示:

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

select @colsUnpivot 
  = stuff((select ','+quotename(C.name)
           FROM sys.columns c
           WHERE c.object_id = OBJECT_ID('dbo.cal') 
           for xml path('')), 1, 1, '')

set @query 
  = 'select data, datename(dw, data) dayname
     from cal
     unpivot
     (
        data
        for d in ('+ @colsunpivot +')
     ) u'

exec sp_executesql @query;

参见带有演示的SQL Fiddle

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.