Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

SQL Server 2008 R2 - Pivot/Unpivot dynamique avec dates (mobiles)

Vous devez d'abord UNPIVOT nos colonnes et utilisez DENSE_RANK() pour vous donner quelque chose sur quoi pivoter plus tard. Mettez ce résultat dans une table temporaire afin que vous puissiez obtenir une liste séparée par des virgules du DESNSE_RANK Colonnes. Créez ensuite une UNION de sorte que Day et Date font partie de la même colonne que ce qui n'était pas pivoté. Cela peut être placé dans une table temporaire globale pour une utilisation dans le SQL dynamique. Créez une variable qui stockera la liste des colonnes et créera le SQL dynamique et l'exécutera.

Un exemple complet (évidemment, ne laissez pas tomber le PhaseFlowChart tableau)

-- pre-cleanup
IF OBJECT_ID('[dbo].[PhaseFlowChart]') IS NOT NULL
    DROP TABLE [dbo].[PhaseFlowChart]
GO

IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
    DROP TABLE #tmp
GO

IF OBJECT_ID('tempdb..##tmp') IS NOT NULL
    DROP TABLE ##tmp
GO

-- setup table and data
CREATE TABLE [dbo].[PhaseFlowChart](
    [pfckey] [int] NULL,
    [hourlykey] [bigint] NULL,
    [daykey] [bigint] NULL,
    [weekkey] [int] NULL,
    [monthkey] [int] NULL,
    [bbkey] [int] NULL,
    [Day] [varchar](100) NULL,
    [Date] [varchar](100) NULL,
    [Bull Bear Gap] [varchar](100) NULL,
    [Monthly] [varchar](100) NULL,
    [Weekly] [varchar](100) NULL,
    [Daily] [varchar](100) NULL,
    [Hour 1] [varchar](100) NULL,
    [Hour 2] [varchar](100) NULL,
    [Hour 3] [varchar](100) NULL,
    [Hour 4] [varchar](100) NULL,
    [Hour 5] [varchar](100) NULL,
    [Hour 6] [varchar](100) NULL,
    [Hour 7] [varchar](100) NULL
) ON [PRIMARY]

INSERT INTO [dbo].PhaseFlowChart 
    ([Day], [Date], [Bull Bear Gap], Monthly, Weekly, Daily, 
        [Hour 1], [Hour 2], [Hour 3], [Hour 4], [Hour 5], [Hour 6], [Hour 7])
VALUES
('MON', '20130101', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1', 'P1'),
('TUE', '20130102', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2', 'P2'),
('WED', '20130103', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3', 'P3'),
('THU', '20130104', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4', 'P4'),
('FRI', '20130105', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5', 'P5'),
('SAT', '20130106', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6', 'P6'),
('SUN', '20130107', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7', 'P7')
GO

-- unpivot the columns into 'categories'
SELECT [Day], [Date], [Value], [Category], 
    DENSE_RANK() OVER (ORDER BY CAST([Date] AS DATE)) dr 
INTO #tmp
FROM PhaseFlowChart pfc
UNPIVOT (
    Value FOR Category IN ([Bull Bear Gap], Monthly, Weekly, Daily, 
                            [Hour 1], [Hour 2], [Hour 3], [Hour 4], 
                                [Hour 5], [Hour 6], [Hour 7])

) upiv

-- create a global temp table for use later
SELECT *
INTO ##tmp
FROM (
      -- union data into single category column
    SELECT 'Day' Category, [Day] Value, dr, 1 o FROM #tmp
    UNION ALL
    SELECT 'Date' Category, [Date] Value, dr, 2 o FROM #tmp
    UNION ALL
    SELECT [Category], Value, dr, 3 o FROM #tmp
) t

-- get a comma seperated list of columns for the PIVOT
DECLARE @cols VARCHAR(MAX) = 
STUFF(CAST((SELECT ',' + QUOTENAME(dr)
       FROM (
           SELECT DISTINCT dr
           FROM #tmp
       ) t
       ORDER BY dr
       FOR XML PATH(''), TYPE
      ) AS VARCHAR(MAX)),1,1,'')

-- create and execute the sql
DECLARE @sql VARCHAR(MAX) = '
    SELECT Category, ' + @cols + '
    FROM ##tmp
    PIVOT (
        MAX([Value])
        FOR dr IN (' + @cols + ')
    ) piv   
      ORDER BY o, CASE Category 
                    WHEN ''Daily'' THEN 4
                    WHEN ''Weekly'' THEN 3
                    WHEN ''Monthly'' THEN 2
                    WHEN ''Bull Bear Gap'' THEN 1
                    ELSE 5 END, Category
'

EXEC(@sql)