2017-04-26 59 views
0

表:多個情況下的SQL查詢檢索單列作爲多列

ID VT_Type1 Vt_type2 VT_Type3 Status_1 Status_2 Status_3 Date_1 Date_2 Date_3 
1  -1  -1  0 X  Y  Z  04/12 05/12 06/12 
2  -1  -1  -1 A  B  C  06/12 07/12 07/10 

預期輸出

Id Type Status Date 
1 1 X  04/12 
1 2 Y  05/12 
2 1 A  06/12 
2 2 B  07/12 
2 3 C  07/10 

如果類型已-1然後相應的狀態和日期欄應作爲行檢索。正如在上面的例子中看到的,ID 1中的type1具有-1,而type2具有-1,所以那些2必須被轉換成2行,類型3具有0,所以不被考慮。當我在網上看到示例時,我看到要使用的案例,但不知道如何使用來維護我的需求。

+2

糟糕的餐桌設計。是否是其他查詢的結果? –

+1

列** Type **中的數據來自哪裏?輸入中沒有任何東西。或者VT_Type1等於1?在這種情況下,您在所需輸出中出現拼寫錯誤,最後一行應該有Type = 3;你將它顯示爲2. – mathguy

+0

另外:你說當輸入「has」(是?)-1時,你想檢索一行,但如果它「有」0則不予考慮。其他價值呢?在你的例子中你有類型= 1,它被認爲是在輸出。所以 - 在輸出中考慮,除非類型爲0?或者,如果不是,**完整**規則是什麼?該類型是否也可以是「空」 - 如果是,應該「考慮」還是忽略它? – mathguy

回答

1

在Oracle 11.1以上,則可以使用UNPIVOT運算符。如果您的數據量很大,這將顯着改善執行時間,因爲它只需要一次讀取表格,而不是使用任何種類的UNION ALL方法讀取三次。

由於DATE是Oracle中的保留字,因此我將列名(在輸出中)從date更改爲dttype並不好(它是一個關鍵字,但它不保留);最好也要避免它。在創建測試數據時,我也將日期視爲字符串,但它與日期的作用相同。

with子句不是解決方案的一部分(不要盲目地將其複製並粘貼到查詢中);我添加它僅用於測試目的。

with 
    test_data (ID, VT_Type1, Vt_type2, VT_Type3, Status_1, Status_2, Status_3, 
                 Date_1, Date_2, Date_3) as (
     select 1, -1, -1, 0, 'X', 'Y', 'Z', '04/12', '05/12', '06/12' from dual union all 
     select 2, -1, -1, -1, 'A', 'B', 'C', '06/12', '07/12', '07/10' from dual 
    ) 
select id, type, status, dt 
from test_data 
unpivot ((vt_type, status, dt) for type in ((vt_type1, status_1, date_1) as 1, 
               (vt_type2, status_2, date_2) as 2, 
               (vt_type3, status_3, date_3) as 3 
              ) 
     ) 
where vt_type != 0 
; 

ID TYPE STATUS DT 
-- ---- ------ ----- 
1  1 X  04/12 
1  2 Y  05/12 
2  1 A  06/12 
2  2 B  07/12 
2  3 C  07/10 
+0

完美的作品。 – Pat

+0

在我的實際表中,如果date_1是varchar數據類型,date_2是日期數據類型,如何修改答案。實際上,在我的桌子上,我有大約15個這樣的欄目,例如我只給出了3欄。 – Pat

+0

無論您使用哪種解決方案,您打算如何解決此問題?任何解決方案都會出現同樣的問題。您可能應該將所有值更改爲日期;要將字符串轉換爲日期,您需要使用'to_date()'和相應的格式模型。如果您在這方面需要更多幫助,那麼最好打開一個單獨的問題,如果您覺得有必要,請將其鏈接回這個問題。在這裏提供的示例中,您只需要兩列(而不是三列),但要確保您發佈的示例數據完全反映了您提出的問題。 – mathguy

1

查詢表三次,一次用於每個類型:

select id, 1 as type, status_1 as status, date_1 as "date" from mytable where VT_Type1 = -1 
union all 
select id, 2 as type, status_2 as status, date_2 as "date" from mytable where VT_Type2 = -1 
union all 
select id, 3 as type, status_3 as status, date_3 as "date" from mytable where VT_Type3 = -1