2013-10-18 28 views
4

我想将行转换为列,按唯一标识符(CASE_ID)分组。SQL将行转换为列(按关键变量分组)?

我有这种结构的表格:

CASE_ID..AMOUNT..TYPE
100 ........ 10 .......甲
100 .... .... 50 ....... B
100 ........ 75 ....... A
200 ........ 33 ..... ..B
200 ........ 10 .......ç

,我试图查询其生产这种结构......

CASE_ID ... AMOUNT_1 ... TYPE_1 ... AMOUNT_2 ... TYPE_2 ... AMOUNT_3 ... TYPE_3
100 ........... 10 ......... .........甲............. 50 ..................乙....... ...... 75 ................... A
200 ........... 33 ........ ..........乙............. 10 .................. C ...... ......(null)...............(null)

(假设更大的数据集包含大量CASE_ID,TYPE和AMOUNT的可能值)

我试图使用枢轴,但我不需要一个聚合函数(只是试图重构数据)。现在我试图以某种方式使用row_number,但不知道如何。

我基本上试图复制和SPSS命令调用Casestovars,但需要能够在SQL中执行它。谢谢。

+0

搜索动态数据透视表,你会发现不少答案。与创建正确的列名和它们内部的值不同的是,聚合并非如此。 –

回答

6

您可以通过创建row_number()顺序号得到的结果,然后使用聚合函数CASE表达式:

select case_id, 
    max(case when seq = 1 then amount end) amount1, 
    max(case when seq = 1 then type end) type1, 
    max(case when seq = 2 then amount end) amount2, 
    max(case when seq = 2 then type end) type2, 
    max(case when seq = 3 then amount end) amount3, 
    max(case when seq = 3 then type end) type3 
from 
(
    select case_id, amount, type, 
    row_number() over(partition by case_id 
         order by case_id) seq 
    from yourtable 
) d 
group by case_id; 

SQL Fiddle with Demo

如果您使用的是具有枢轴功能的数据库产品,那么你可以使用row_number()与PIVOT,但首先我建议你先UNPIVOT的amounttype列。对于价值观的SQL Server中的有限数量的基本语法是:

select case_id, amount1, type1, amount2, type2, amount3, type3 
from 
(
    select case_id, col+cast(seq as varchar(10)) as col, value 
    from 
    (
    select case_id, amount, type, 
     row_number() over(partition by case_id 
         order by case_id) seq 
    from yourtable 
) d 
    cross apply 
    (
    select 'amount', cast(amount as varchar(20)) union all 
    select 'type', type 
) c (col, value) 
) src 
pivot 
(
    max(value) 
    for col in (amount1, type1, amount2, type2, amount3, type3) 
) piv; 

SQL Fiddle with Demo

如果你有一个未知的数值,那么你可以使用动态SQL得到的结果 - SQL Server语法是:

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 case_id 
               order by case_id) seq 
         from yourtable 
        ) d 
        cross apply 
        (
         select 'amount', 1 union all 
         select 'type', 2 
        ) c (col, so) 
        group by col, so 
        order by seq, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT case_id,' + @cols + ' 
      from 
      (
       select case_id, col+cast(seq as varchar(10)) as col, value 
       from 
       (
        select case_id, amount, type, 
        row_number() over(partition by case_id 
             order by case_id) seq 
        from yourtable 
       ) d 
       cross apply 
       (
        select ''amount'', cast(amount as varchar(20)) union all 
        select ''type'', type 
       ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo。每个版本将给出结果:

| CASE_ID | AMOUNT1 | TYPE1 | AMOUNT2 | TYPE2 | AMOUNT3 | TYPE3 | 
|---------|---------|-------|---------|-------|---------|--------| 
|  100 |  10 |  A |  50 |  B |  75 |  A | 
|  200 |  33 |  B |  10 |  C | (null) | (null) |