2013-03-21 26 views
0

我已經在SQL Server中得到這個結果數據2008 R2SQL Server組的列行(支點?)

id  Size Acted Sum  Avg1 Avg2 A1  A2  A3 
1  3921 39  690  17.69 0.18 NULL  NULL NULL 
40  11979 301  5944.26 19.75 0.5 10000.00 2000.00 1000.00 
41  11714 289  5060 17.51 0.43 10000.00 3000.00 2000.00 
42  11599 265  4107.98 15.5 0.35 10000.00 5000.00 500.00 

而且我想根據ID,所以我將收到的列移動到行此結果:

id1  id40  id41   id42 
1   40   41   42 
3921  11979  11714  11599 
39   301  289   265 
690  5944  5060   4107 
17.69  19.75  17.51  15.5 
0.18  0.5  0.43   0.35 
      10000.00 2000.00  1000.00 
      10000.00 3000.00  2000.00 
      10000.00 5000.00  500.00 

有沒有辦法做到這一點? 我試過支點,但據我所知,我只能在這種情況下轉換1列,並沒有多少需要。

回答

4

爲了得到這個結果,你會先將unpivot的數據從列到行,然後應用PIVOT函數。

由於您使用的是SQL Server 2008,因此您可以使用CROSS APPLYVALUES來反轉數據。這將從您的衆多列中獲取值並將它們轉換爲行:

select 'id'+cast(t.id as varchar(10)) p_id, 
    c.col, 
    c.value, 
    c.sort_order 
from yourtable t 
cross apply 
(
    values 
    (1, 'id', id), 
    (2, 'size', size), 
    (3, 'acted', acted), 
    (4, 'sum', sum), 
    (5, 'avg1', avg1), 
    (6, 'avg2', avg2), 
    (7, 'a1', a1), 
    (8, 'a2', a2), 
    (9, 'a3', a3) 
) c (sort_order, col, value) 

請參閱SQL Fiddle with Demo。一旦數據未經轉化,您就可以使用id值的新列進行調整。因此,完整的代碼是:

select col, 
    id1, 
    id40, 
    id41, 
    id42 
from 
(
    select 'id'+cast(t.id as varchar(10)) p_id, 
    c.col, 
    c.value, 
    c.sort_order 
    from yourtable t 
    cross apply 
    (
    values 
     (1, 'id', id), 
     (2, 'size', size), 
     (3, 'acted', acted), 
     (4, 'sum', sum), 
     (5, 'avg1', avg1), 
     (6, 'avg2', avg2), 
     (7, 'a1', a1), 
     (8, 'a2', a2), 
     (9, 'a3', a3) 
) c (sort_order, col, value) 
) src 
pivot 
(
    max(value) 
    for p_id in (id1, id40, id41, id42) 
) piv 
order by sort_order; 

請參閱SQL Fiddle with Demo

如果您不能使用CROSS APPLYVALUES,那麼這也可以做,使用UNPIVOT功能:

select col, 
    id1, id40, id41, id42 
from 
(
    select 'id'+cast(id_piv as varchar(10)) id, 
    col, 
    value, 
    case col 
     when 'id' then 1 
     when 'size' then 2 
     when 'acted' then 3 
     when 'sum' then 4 
     when 'avg1' then 5 
     when 'avg2' then 6 
     when 'a1' then 7 
     when 'a2' then 8 
     when 'a3' then 9 end sort_order 
    from 
    (
    select id id_piv, 
     cast(id as numeric(10, 2)) id, 
     cast(size as numeric(10, 2)) size, 
     cast(acted as numeric(10, 2)) acted, 
     sum, avg1, avg2, A1, A2, A3 
    from yourtable 
) d 
    unpivot 
    (
    value 
    for col in (id, size, acted, sum, avg1, avg2, a1, a2, a3) 
    ) unpiv 
) src 
pivot 
(
    max(value) 
    for id in (id1, id40, id41, id42) 
) piv 
order by sort_order; 

SQL Fiddle with Demo

最後,如果你將有數目不詳的id值要轉換爲列,那麼您將需要使用動態sql:

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

select @cols = STUFF((SELECT ',' + QUOTENAME('id'+cast(id as varchar(10))) 
        from yourtable 
        group by id 
        order by id 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT col, ' + @cols + ' 
       from 
      (
       select ''id''+cast(t.id as varchar(10)) p_id, 
        c.col, 
        c.value, 
        c.sort_order 
       from yourtable t 
       cross apply 
       (
        values 
        (1, ''id'', id), 
        (2, ''size'', size), 
        (3, ''acted'', acted), 
        (4, ''sum'', sum), 
        (5, ''avg1'', avg1), 
        (6, ''avg2'', avg2), 
        (7, ''a1'', a1), 
        (8, ''a2'', a2), 
        (9, ''a3'', a3) 
       ) c (sort_order, col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for p_id in (' + @cols + ') 
      ) p 
      order by sort_order' 

execute(@query) 

SQL Fiddle with Demo

所有版本的結果:

| COL | ID1 | ID40 | ID41 | ID42 | 
---------------------------------------------- 
| id |  1 |  40 | 41 |  42 | 
| size | 3921 | 11979 | 11714 | 11599 | 
| acted |  39 |  301 | 289 |  265 | 
| sum | 690 | 5944.26 | 5060 | 4107.98 | 
| avg1 | 17.69 | 19.75 | 17.51 | 15.5 | 
| avg2 | 0.18 |  0.5 | 0.43 | 0.35 | 
| a1 | (null) | 10000 | 10000 | 10000 | 
| a2 | (null) | 2000 | 3000 | 5000 | 
| a3 | (null) | 1000 | 2000 |  500 |