2013-10-27 56 views
2

我已经发布了一个数据透视问题并且已被回答。但是,这种特殊情况需要日期作为标题,并且日期会在每次生成数据透视时更改(并且未知)。我相信我需要基于几个样本的动态pivot/unpivot,但我无法确定语法。SQL Server 2008 R2 - 带有(移动)日期的动态数据透视表/ Unpivot

下面是表:

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] 

我不需要输出任何“关键”列。因此,这里是餐桌上的简单的选择:

select [DAY],[Date],[Bull Bear Gap],[Monthly],[Weekly],[Daily],[Hour 1],[Hour 2],[Hour 3],[Hour 4],[Hour 5],[Hour 6],[Hour 7] 
from PhaseFlowChart 
order by pfckey asc 

这里是从上面的输出:

enter image description here

我想要的输出(动态旋转/ UNPIVOT?),看起来像这样(又一次,日期将在生成的每个时间是每天)是不同的:

enter image description here

最后,我发现这在网络上的SQL,但经过几天操纵语法,我无法弄清楚如何移植它以满足我的需求。

CREATE TABLE #yt 
    ([ID] int, [expense] int, [revenue] int, [date] datetime) 
; 

INSERT INTO #yt 
    ([ID], [expense], [revenue], [date]) 
VALUES 
    (1, 43, 45, '2012-12-31 00:00:00'), 
    (2, 32, 32, '2013-01-01 00:00:00'), 
    (3, 64, 56, '2013-01-31 00:00:00'), 
    (4, 31, 32, '2013-03-03 00:00:00') 

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

select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+'_'+convert(varchar(10), #yt.date, 110)) 
        from #yt 
        cross apply 
        (
         select 'expense' col union all 
         select 'revenue' 
        ) c 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT id,' + @cols + ' 
      from 
      (
       select id, 
       col+''_''+convert(varchar(10), date, 110) new_col, 
       value 
       from #yt 
       unpivot 
       (
       value 
       for col in (expense, revenue) 
      ) un 
      ) src 
      pivot 
      (
       sum(value) 
       for new_col in (' + @cols + ') 
      ) p ' 

execute(@query); 

任何/所有的帮助是非常感谢。

回答

3

您首先需要UNPIVOT我们的专栏,并使用DENSE_RANK()给你稍后转动的东西。把这个结果放到一个临时表中,这样你就可以得到一个逗号分隔列表DESNSE_RANK列。然后创建一个UNION,这样DayDate与未转义的列是同一列的一部分。这可以放在全局临时表中以便在动态SQL中使用。创建一个变量来存储列的列表并构建动态SQL并执行它。

完整的例子(显然不走丢弃PhaseFlowChart表)

-- 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) 
+0

T I辉煌,正是我需要的谢谢。除了使用这个,我还会学习你的SQL来提高我的主轴,不透明度和动态SQL技能。谢谢,我真的很感激。 –

+0

T我 - 对不起,最后一个问题。除了面向日期的列不是最早到最新,从左到右的顺序之外,它都运行良好。我试图通过声明来摆弄订单,但还没有弄明白。我怎样才能让日期栏显示最老的最左边和最近的最右边?谢谢! –

+0

尝试在'FROM#tmp'后面的'@ cols'的查询中放置'ORDER BY' –