Pasar nombres de columnas dinámicamente a UNPIVOT

10

Tengo una tabla con los siguientes datos

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

Y usando UNPIVOT

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

Obtengo el siguiente resultado

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

Ahora mi pregunta es si podemos pasar los nombres de las columnas dinámicamente para UNPIVOTque cuando las columnas en la tabla aumenten no tengamos que alterar la declaración.

Sai Chaitanya M
fuente

Respuestas:

14

Si va a tener un número desconocido de columnas que necesitará desenredar, entonces tendrá que buscar implementar SQL dinámico.

Puede usar sys.columnspara obtener los nombres de todas las columnas de su caltabla. Si utiliza la siguiente consulta, obtendrá la lista de todas las columnas de su tabla:

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

Ahora puede usar esta consulta junto con FOR XML PATHpara crear una lista separada por comas de los nombres que se concatenarán a una cadena que se ejecutará:

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

Finalmente, tomará esta lista y la colocará en su cadena de consulta para que se ejecute de modo que la consulta completa se vea así:

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;

Ver SQL Fiddle con Demo

Taryn
fuente