2013-08-19 65 views
0

我有一個問題,這看起來更好的方式在SQLfiddle: http://www.sqlfiddle.com/#!3/dffa1/2SQL Pivoting或轉置或...行到列?

我有一個表multirows與郵戳和測試結果每一個用戶,我想調換或者轉動成一行結果如下,其中每個用戶列出了所有的時間和價值的結果:

USERID PSA1_time PSA1_result PSA2_time PSA2_result PSA3_time PSA3_result ... 


1  1999-.... 2   1998... 4   1999... 6 

3  1992... 4   1994  6 

4  2006 ... 8 

見下表:

CREATE TABLE yourtable 
    ([userid] int, [Ranking] int,[test] varchar(3), [Date] datetime, [result] int) 
; 

INSERT INTO yourtable 
    ([userid], [Ranking],[test], [Date], [result]) 
VALUES 
    ('1', '1', 'PSA', 1997-05-20, 2), 
    ('1', '2','PSA', 1998-05-07, 4), 
    ('1', '3','PSA', 1999-06-08, 6), 
    ('1', '4','PSA', 2001-06-08, 8), 
    ('1', '5','PSA', 2004-06-08, 0), 
     ('3', '1','PSA', 1992-05-07, 4), 
    ('3', '2','PSA', 1994-06-08, 6), 
    ('4', '1','PSA', 2006-06-08, 8) 
; 
+0

我不明白你想要的結果,你能澄清一下你有興趣看到什麼嗎?即'1 1999 -... 2'這些值不會同時出現在您的示例數據中。 –

+0

我想用戶1已將所有信息列在一行中。因爲它是多行中每個測試結果與datestamp。即用戶1 - 具有不同日期和時間的四個結果。我希望用戶1將所有信息放在一行中:用戶1,test1,timeOftest1,resultOftest1,timeOftest2,resultOftest2 ...。現在用戶不總是有相同數量的結果。這是否更有意義?並感謝Formating。 – user2696868

回答

0

既然要樞兩列我的建議是要首先輸入dateresult列,然後應用PIVOT功能。

的逆轉置過程將dateresult轉換兩列到多行:

select userid, 
    col = test +'_'+cast(ranking as varchar(10))+'_'+ col, 
    value 
from yourtable t1 
cross apply 
(
    select 'time', convert(varchar(10), date, 120) union all 
    select 'result', cast(result as varchar(10)) 
) c (col, value) 

Demo。這會給你一個結果:

| USERID |   COL |  VALUE | 
-------------------------------------- 
|  1 | PSA_1_time | 1997-05-20 | 
|  1 | PSA_1_result |   2 | 
|  1 | PSA_2_time | 1998-05-07 | 
|  1 | PSA_2_result |   4 | 
|  1 | PSA_3_time | 1999-06-08 | 

既然你有這個格式的數據,那麼你可以申請支點,以獲得col每個項目的max/min值:

如果你有一個數量有限列,那麼你可以硬編碼查詢:

select * 
from 
(
    select userid, 
    col = test +'_'+cast(ranking as varchar(10))+'_'+ col, 
    value 
    from yourtable t1 
    cross apply 
    (
    select 'time', convert(varchar(10), date, 120) union all 
    select 'result', cast(result as varchar(10)) 
) c (col, value) 
) d 
pivot 
(
    max(value) 
    for col in (PSA_1_time, PSA_1_result, 
       PSA_2_time, PSA_2_result, 
       PSA_3_time, PSA_3_result, 
       PSA_4_time, PSA_4_result, 
       PSA_5_time, PSA_5_result) 
) piv; 

SQL Fiddle with Demo

如果你有未知列,那麼您將需要使用動態SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(test +'_'+cast(ranking as varchar(10))+'_'+ col) 
        from yourtable 
        cross apply 
        (
         select 'time', 1 union all 
         select 'result', 2 
        ) c (col, so) 
        group by test, ranking, col, so 
        order by Ranking, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 


set @query = 'SELECT userid,' + @cols + ' 
      from 
      (
       select userid, 
       col = test +''_''+cast(ranking as varchar(10))+''_''+ col, 
       value 
       from yourtable t1 
       cross apply 
       (
       select ''time'', convert(varchar(10), date, 120) union all 
       select ''result'', cast(result as varchar(10)) 
      ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

請參閱SQL Fiddle with Demo。兩個版本都會給出結果:

| USERID | PSA_1_TIME | PSA_1_RESULT | PSA_2_TIME | PSA_2_RESULT | PSA_3_TIME | PSA_3_RESULT | PSA_4_TIME | PSA_4_RESULT | PSA_5_TIME | PSA_5_RESULT | 
------------------------------------------------------------------------------------------------------------------------------------------------------ 
|  1 | 1997-05-20 |   2 | 1998-05-07 |   4 | 1999-06-08 |   6 | 2001-06-08 |   8 | 2004-06-08 |   0 | 
|  3 | 1992-05-07 |   4 | 1994-06-08 |   6 |  (null) |  (null) |  (null) |  (null) |  (null) |  (null) | 
|  4 | 2006-06-08 |   8 |  (null) |  (null) |  (null) |  (null) |  (null) |  (null) |  (null) |  (null) | 
+0

這正是我所需要的 - 我現在玩它 - 非常感謝 – user2696868

+0

如何將所有這些保存到臨時表中? – user2696868

+0

@ user2696868如果您有新問題,請使用提問併發布新要求。 – Taryn