2013-08-19 29 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