2013-08-01 42 views
0

我將不勝感激。我有如下數據的SQL Server數據庫稱爲info_source表:SQL Server將行移動到列

Date  StatCode Value_1 Value_2 Remarks 
---------- -------- ------- ------- ------- 
2012-11-01 SRC_1  18775  648  Normal 
2012-11-01 SRC_2  308218 249  Normal 
2012-11-01 SRC_3  0   0  Off 
2012-11-02 SRC_4  123181 523  Normal 
2012-11-02 SRC_5  189231 247  Normal 

我會用一個加盟站的名稱替換statCode領域。我想轉換成列在報表中類似的東西來這行:

Date  StatName Value_1 Value_2 Remarks StatName Value_1 Value_2 Remarks 
---------- ---------- ------- ------- ------- ---------- ------- ------- ------- 
2012-11-01 (SRC_1)ABC 18775 648  Normal (SRC_2)DEF 308218 249  Normal 
2012-11-02 (SRC_4)JKL 123181 523  Normal (SRC_5)MNO 189231 247  Normal 

我要創建一個視圖,但未能解決問題。比我研究和發現關於數據透視表的一些信息,但我無法抓住如何編寫一個我想要的查詢。

編輯

這是我到目前爲止已經試過:

SELECT * FROM (
SELECT date AS [date], statCode AS [station], value_1 AS [val1], 
value_2 AS [val2], remarks AS [remks] FROM info_source 
) AS query1 
+2

歡迎使用堆棧溢出。即使你嘗試過的東西不起作用,我們也很欣賞看到這些代碼。這證明你已經做了一個嘗試,並阻止你獲得你已經嘗試過的答案。 –

+0

SRC_3行發生了什麼? –

+0

@AaronBertrand我刪除了那一行。 – tanner

回答

2

爲了你得到的結果,我的建議是使用row_number()窗函數,UNPIVOT你列statcodevalue_1,value_2remarks,最後應用PIVOT功能。

第一步是查詢您的數據並應用row_number()函數。由於您有在列要多行數據,您需要一種方法來保持相互關聯的值:

select date, value_1, value_2, statcode, remarks, 
    row_number() over(partition by date 
        order by statcode) seq 
from yourtable; 

Demo。這將爲表格中的每個日期的每行分配一個連續編號。我使用order by statcode,但如果您有另一個值來保持項目的特定順序,那麼您將使用該列。

一旦您指定的行數,那麼你將在列statcodevalue_1value_2remarks unpivot的數據。您可以使用UNPIVOT函數,也可以使用CROSS APPLY將多列轉換爲多行數據。當你改變你將留下3列,日期,上一列的值,然後將在PIVOT使用新列名的數據:

select date, 
    col = col+'_'+cast(seq as varchar(10)), 
    value 
from 
(
    select date, value_1, value_2, statcode, remarks, 
    row_number() over(partition by date 
         order by statcode) seq 
    from yourtable 
) src 
cross apply 
(
    select 'statcode', statcode union all 
    select 'value_1', cast(value_1 as varchar(10)) union all 
    select 'value_2', cast(value_2 as varchar(10)) union all 
    select 'remarks', remarks 
) c (col, value); 

Demo。這會給你的數據格式:

|       DATE |  COL | VALUE | 
--------------------------------------------------------- 
| November, 01 2012 00:00:00+0000 | statcode_1 | SRC_1 | 
| November, 01 2012 00:00:00+0000 | value_1_1 | 18775 | 
| November, 01 2012 00:00:00+0000 | value_2_1 | 648 | 
| November, 01 2012 00:00:00+0000 | remarks_1 | Normal | 
| November, 01 2012 00:00:00+0000 | statcode_2 | SRC_2 | 
| November, 01 2012 00:00:00+0000 | value_1_2 | 308218 | 

最後將應用旋轉功能的項目在新的專欄中,我叫col

select date, 
    statcode_1, value_1_1, value_2_1, remarks_1, 
    statcode_2, value_1_2, value_2_2, remarks_2, 
    statcode_3, value_1_3, value_2_3, remarks_3 
from 
(
    select date, 
    col = col+'_'+cast(seq as varchar(10)), 
    value 
    from 
    (
    select date, value_1, value_2, statcode, remarks, 
     row_number() over(partition by date 
         order by statcode) seq 
    from yourtable 
) src 
    cross apply 
    (
    select 'statcode', statcode union all 
    select 'value_1', cast(value_1 as varchar(10)) union all 
    select 'value_2', cast(value_2 as varchar(10)) union all 
    select 'remarks', remarks 
) c (col, value) 
) d 
pivot 
(
    max(value) 
    for col in (statcode_1, value_1_1, value_2_1, remarks_1, 
       statcode_2, value_1_2, value_2_2, remarks_2, 
       statcode_3, value_1_3, value_2_3, remarks_3) 
) piv; 

SQL Fiddle with Demo。現在上面的代碼會爲你工作,你有一個已知的值,但如果你有未知的值,那麼你將需要使用動態SQL。動態SQL代碼:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(col+'_'+cast(seq as varchar(10))) 
        from 
        (
         select row_number() over(partition by date 
               order by statcode) seq 
         from yourtable 
        ) t 
        cross apply 
        (
         select 'statcode', 1 union all 
         select 'value_1', 2 union all 
         select 'value_2', 3 union all 
         select 'remarks', 4 
        ) c (col, so) 
        group by col, seq, so 
        order by seq, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT date,' + @cols + ' 
      from 
      (
       select date, 
       col = col+''_''+cast(seq as varchar(10)), 
       value 
       from 
       (
       select date, value_1, value_2, statcode, remarks, 
        row_number() over(partition by date 
            order by statcode) seq 
       from yourtable 
      ) src 
       cross apply 
       (
       select ''statcode'', statcode union all 
       select ''value_1'', cast(value_1 as varchar(10)) union all 
       select ''value_2'', cast(value_2 as varchar(10)) union all 
       select ''remarks'', remarks 
      ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo。兩種版本都會給出結果:

|       DATE | STATCODE_1 | VALUE_1_1 | VALUE_2_1 | REMARKS_1 | STATCODE_2 | VALUE_1_2 | VALUE_2_2 | REMARKS_2 | STATCODE_3 | VALUE_1_3 | VALUE_2_3 | REMARKS_3 | 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
| November, 01 2012 00:00:00+0000 |  SRC_1 |  18775 |  648 | Normal |  SRC_2 | 308218 |  249 | Normal |  SRC_3 |   0 |   0 |  Off | 
| November, 02 2012 00:00:00+0000 |  SRC_4 | 123181 |  523 | Normal |  SRC_5 | 189231 |  247 | Normal |  (null) | (null) | (null) | (null) | 
+0

感謝您的幫助。我會試一試。 – tanner