0

我在 SQL Server 2008 R2 中有这个结果数据

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

1 回答 1

4

为了得到这个结果,您首先需要数据从列中转为行,然后应用该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 APPLYand VALUES,那么也可以使用以下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

最后,如果您想要将未知数量的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

所有版本的结果:

|   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 |
于 2013-03-21T10:40:15.217 回答