2013-10-27 94 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' –