2016-09-19 52 views
2

所以我有這個表分類在SELECT語句

id  | object |  type 
-------------------------------- 
1  | blue  |  color 
1  | burger |  food 
2  | sandwich |  food 
2  | red  |  color 
2  | coke  |  beverage 
3  | sprite |  beverage 
3  | coke  |  beverage 
3  | red  |  color 
4  | bacon  |  food 

我要創建一個select語句,將顯示的列編號,顏色,食品和飲料的表。由ID和他們指定的東西安排在它上面。

所以我預期的結果是

id  | color | food | beverage 
------------------------------------------- 
1  | blue | burger | 
2  | red  | sandwich | coke 
3  | red  |   | sprite 
3  |   |   | coke 
4  |   | bacon | 

截至目前我有這樣的代碼

Select id as id, 
Case When I.Type = 'color' Then I.Object End As color, 
Case When I.Type = 'food' Then I.Object End As food, 
Case When I.Type = 'beverage' Then I.Object End As beverage 
From table I 
order by id 

,但我的代碼的問題是,它不按它的ID,因此它爲每多行目的。

TIA!

+0

通過什麼規則是 「精靈」 和 「紅色」 和 「可樂」 與NULL進行相關的關聯ID = 3?爲什麼不相反呢?它是隨機的(所以解決相同問題的其他人可能會得到不同的解決方案,這兩種解決方案同樣有效)?還是有額外的規則? – mathguy

回答

1

您正在尋找數據透視查詢。關於您的問題的挑戰在於,對於給定的idtype,可以存在多於一個的object。爲了解決這個問題,你可以使用LISTAGG首先做一個GROUP BY查詢到給定類型的CSV聚合對象:

SELECT id, 
     MAX(CASE WHEN t.type = 'color' THEN t.object ELSE NULL END) AS color, 
     MAX(CASE WHEN t.type = 'food'  THEN t.object ELSE NULL END) AS food, 
     MAX(CASE WHEN t.type = 'beverage' THEN t.object ELSE NULL END) AS beverage 
FROM 
(
    SELECT id, 
      LISTAGG(object, ',') WITHIN GROUP (ORDER BY object) AS object, 
      type 
    FROM yourTable 
    GROUP BY id, type 
) t 
GROUP BY t.id 

內查詢首先在兩個idtype,而外部查詢聚集的對象是一個簡單的數據透視查詢,你可能期望。

這裏是一個小提琴,顯示在MySQL幾乎相同的查詢(甲骨文似乎被永遠打破):

SQLFiddle

+0

它不顯示所有對象的ID只有1行每個ID正在啓動 –

+0

你能告訴我如何樞軸查詢可以與我的問題工作? @tim –

+0

@robing - 「pivot」不是解決您的問題的方法。在'pivot'操作中,每個id應該只有一行; 'pivot'是一個聚合操作,與'sum'和'count'類似 - 每個組只有一個結果。再說一遍:你試圖做的不是「樞軸」操作。 – mathguy

0

試試這個

我已經實現了使用pivot條款

select id,object,type from yourtable 
pivot 
(
    LISTAGG(object, ',') WITHIN GROUP (ORDER BY object) 
    for type IN 
       (
        'color' AS "color", 
        'food' AS "food", 
        'beverage' AS "beverage" 
       ) 
) 
order by id 
1

你可以嘗試類似下面的東西:

with test(id, object, type) as 
(
    select 1,'blue', 'color' from dual union all 
    select 1,'burger', 'food' from dual union all 
    select 2,'sandwich','food' from dual union all 
    select 2,'red',  'color' from dual union all 
    select 2,'coke', 'beverage' from dual union all 
    select 3,'sprite', 'beverage' from dual union all 
    select 3,'coke', 'beverage' from dual union all 
    select 3,'red',  'color' from dual union all 
    select 4,'bacon', 'food' from dual 
) 
select id, 
     max(case when type = 'color'  
       then object 
       else null 
      end 
     ) as color, 
     max(case when type = 'food'  
       then object 
       else null 
      end 
     ) as food, 
     max(case when type = 'beverage'  
       then object 
       else null 
      end 
     ) as beverage 
from (
     select id, object, type, row_number() over (partition by id, type order by object) row_for_id 
     from test 
    ) 
group by id, row_for_id 
order by id, row_for_id 

內部查詢是主要部分,您可以在其中處理具有許多類型對象的單個id的情況;您可以通過編輯order by object來修改訂購。 可以用不同的方式重寫外部查詢,例如使用PIVOT;我用MAX希望能夠說清楚。

0

羅賓:我對你的評論(在Tim Biegeleisen的回答下)是部分不正確的。有一個基於數據透視的解決方案;然而,這些「羣體」不是通過身份證,而是通過身份和排名在你的三個「類別」中。對於此解決方案(或任何不使用動態SQL的解決方案)來說,必須事先知道所有「類型」(及其名稱),並且它們必須在SQL查詢中進行硬編碼。

注意:在此解決方案中,我假設對於每個id,同一個「類型」內的「對象」根據它們的字母順序相互關聯(例如,對於id = 3,「焦炭「與」red「關聯,」sprite「與NULL關聯,與您的示例輸出不同)。我在問題的下面問你 - 如果你還沒有與我們分享的其他規則,要求不同類型的對象的不同配對,則可能或不可能根據這些附加規則來調整解決方案。

編輯:仔細一看,這幾乎是Aleksej提供的,而不使用明確的pivot語法。他的解決方案的優點是它可以在Oracle的舊版本中工作(在11.1之前,其中pivot首次可用)。

查詢(包括在第一CTE測試數據):

with 
    inputs (id, object, type) as (
     select 1, 'blue'  , 'color' from dual union all 
     select 1, 'burger' , 'food'  from dual union all 
     select 2, 'sandwich' , 'food'  from dual union all 
     select 2, 'red'  , 'color' from dual union all 
     select 2, 'coke'  , 'beverage' from dual union all 
     select 3, 'sprite' , 'beverage' from dual union all 
     select 3, 'coke'  , 'beverage' from dual union all 
     select 3, 'red'  , 'color' from dual union all 
     select 4, 'bacon' , 'food'  from dual 
    ), 
    r (id, object, type, rn) as (
     select id, object, type, row_number() over (partition by id, type order by object) 
     from inputs 
    ) 
select id, color, food, beverage 
from r 
    pivot (max(object) for type in ('color' as color, 'food' as food, 
            'beverage' as beverage)) 
order by id, rn 
; 

OUTPUT:

ID COLOR FOOD  BEVERAGE 
---- -------- -------- -------- 
    1 blue  burger 
    2 red  sandwich coke 
    3 red    coke 
    3     sprite 
    4   bacon