2013-10-27 3 views
2

Я отправил сводный вопрос раньше, и на него был дан ответ. Однако для этого конкретного случая требуются даты, так как заголовки и даты будут меняться (и быть неизвестными) каждый раз, когда генерируется стержень. Я считаю, что мне нужен динамический pivot/univot, основанный на нескольких образцах, но я не могу понять синтаксис.SQL Server 2008 R2 - Динамический Pivot/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

Прежде всего, необходимо, чтобы наши колонны и использовали DENSE_RANK(), чтобы дать вам возможность повернуть дальше. Поместите этот результат в временную таблицу, чтобы вы могли получить разделенный запятыми список столбцов DESNSE_RANK. Затем создайте UNION так, чтобы Day и Date являются частью того же столбца, что и для удобства использования. Это можно поместить в глобальную временную таблицу для использования в динамическом 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 I - Извините, последний вопрос. Все работает хорошо, за исключением того, что столбцы, ориентированные на дату, не относятся к самым старым и новейшим, слева направо. Я пробовал возиться с заявлением, но пока не понял. Как мне получить столбцы даты, чтобы отображать самые старые самые дальние слева и самые последние вправо? Благодаря! –

+0

попробуйте поместить 'ORDER BY' в запрос для' @ cols' сразу после 'FROM # tmp' –

Смежные вопросы