将列名动态传递给 UNPIVOT

Sai*_*a M 11 sql-server sql-server-2008-r2 unpivot

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

First         Second        Third         Fourth        Fifth         Sixth
2013-08-20    2013-08-21    2013-08-22    2013-08-23    2013-08-24    2013-08-25
Run Code Online (Sandbox Code Playgroud)

并使用 UNPIVOT

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

我得到以下结果

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
Run Code Online (Sandbox Code Playgroud)

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

Tar*_*ryn 14

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

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

select C.name
from sys.columns c
where c.object_id = OBJECT_ID('dbo.cal') 
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用此查询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, '')
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

参见SQL Fiddle with Demo