2013-10-18 30 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) |