2016-07-01 19 views
0

針對Oracle 12c ...我有一個銷售給公司的行項目表。這張表格有賣給這家公司的銷售代表的三層級別。其中一列是公司名稱。我需要幫助編寫SQL,以便跨銷售給該公司的所有行在所有三列中生成逗號分隔的所有人員名稱的唯一列表。舉個例子...Oracle使用ListAgg,跨多列的不同值

CompanyName Rep  Manager  GVP 
----------- ------- -------- -------- 
Sears  Bob  Tim  Frank 
Sears  Jack  Tim  Frank 
Ace   Scott Chris  Bill 

當我看看西爾斯時,SQL應該返回'Bob,Jack,Tim,Frank'。名稱的順序無關緊要,只是它們是唯一的,並且它們包含來自所有3個字段的名稱。我會認爲這是一種LISTAGG查詢的,但可能是錯誤的...

回答

3

使用UNPIVOT運算符(它只會做一個表掃描,而使用UNION通常會做每一個SELECT表掃描中被聯合聲明):

甲骨文設置

CREATE TABLE table_name (CompanyName, Rep, Manager, GVP) AS 
SELECT 'Sears', 'Bob', 'Tim', 'Frank' FROM DUAL UNION ALL 
SELECT 'Sears', 'Jack', 'Tim', 'Frank' FROM DUAL UNION ALL 
SELECT 'Ace', 'Scott', 'Chris', 'Bill' FROM DUAL; 

查詢

SELECT CompanyName, 
     LISTAGG(Name, ',') WITHIN GROUP (ORDER BY Name) AS Names 
FROM (
    SELECT DISTINCT 
     CompanyName, 
     Name 
    FROM table_name 
    UNPIVOT(name FOR typ IN (Rep, Manager, GVP)) 
) 
GROUP BY CompanyName; 

輸出

COMPANYNAME NAMES 
----------- ------------------ 
Ace   Bill,Chris,Scott 
Sears  Bob,Frank,Jack,Tim 
+0

我選擇這種方法作爲答案,因爲它只需要一次讀取數據。作爲獎勵,我必須承認,我從來沒有見過以這種方式使用CTAS(創建選擇表)。我喜歡。 – user1009073

2

您需要unpivot的數據(除去重複),然後reaggregate它:

select companyname, listagg(person, ',') within group (order by person) as persons 
from ((select companyname, repfrom as person t) union 
     (select companyname, manager from t) union 
     (select companyname, gvp from t) 
    ) t 
group by companyname; 
0

這SQL應該做的訣竅:

select listagg(p, ', ') within group (order by p) from (
    select rep p 
    from your_table 
    union 
    select manager p 
    from your_table 
    union 
    select gvp p 
    from your_table); 
+0

這不分區由'CompanyName'名稱。 – MT0

+0

是的,這是正確的,但它顯示了首先使用'UNION'去除重複,然後'LISTAGG'到聚合的一般想法。 –