2016-07-22 45 views
1

我正在學習Oracle SQL,並且遇到了與當前查詢有關的問題。我正在處理幾個VIEW,這些VIEW是一對多的關係。Oracle從衆多JOIN中選擇一對多返回重複項

我得到了LISTAGG查詢的工作,這很好。

現在,我增加了一對多VIEW_PHONE到我的查詢。

我試着看着樞軸,但我得到了一點失落。我發現這個查詢使用Max,Case並且它自己可以工作。當我爲合併

個人,企業和家庭電話號碼的電話Case語句,結果有重複技巧串。

這裏是輸出

之前添加VIEW_PHONE

1  John M. Doe JDOE 1:1, 2:2, 3:3, 4:4  

添加VIEW_PHONE內加入

1  John M. Doe  JDOE  111-111-1111, 222-222-2222, 333-333-3333, 1;1, 1:1, 1:1, 2:2,2:2,2:2, 3:3, 3:3, 3:3, 4:4,4:4,4:4 

我注意到,如果我改變內部連接語句PHONE.PHONE_TYPE(家庭之後','BUSINESS','CELL')改爲PHONE.PHONE_TYPE('HOME'),它只會給出一個技能字符串,而不是3.由於我正在嘗試獲取3個電話號碼,因此影響了我與第e VIEW_SKILL。

如何解決此查詢不重複技能字符串。謝謝..

SELECT PERSON.PERSON_ID, PERSON.FIRST_NAME, PERSON.MIDDLE_NAME, PERSON.LAST_NAME,  
     PERSON.USER_NAME, 
     max(case when PHONE_TYPE = 'HOME' then PHONE_NUMBER end) as HOME_PHONE, 
     max(case when PHONE_TYP= 'BUSINESS' then PHONE_NUMBER end) as BUSINESS_PHONE, 
     max(case when PHONE_TYP= 'CELL' then PHONE_NUMBER end) as CELL_PHONE, 
     LISTAGG(case when SKILLS.SKILL_DESC = '1' then '1:1' 
        when SKILLS.SKILL_DESC = '2' then '2:2' 
        when SKILLS.SKILL_DESC = '3' then '3:3' 
        when SKILLS.SKILL_DESC = '4' then '4:4' 
    when SKILL_DESC = 'ADMIN' AND PERSON.DEPT= 'DEPT1' then 'DEPT1:ADMIN' 
    when SKILL_DESC = 'ADMIN' AND PERSON.DEPT= 'DEPT2' then 'DEPT2:ADMIN' 
        else '' 
       end, ',') WITHIN GROUP (ORDER BY SKILLS.SKILL_SHORT_DESC) AS Speciality 
FROM VIEW_PERSON PERSON INNER JOIN 
    (SELECT DISTINCT PERSON_ID, PHONE_TYPE, PHONE_NUMBER FROM VIEW_PHONE 
    ) PHONE 
    ON PHONE.PERSON_ID = PERSON.PERSON_ID AND PHONE.PHONE_TYPE('HOME', 'BUSINESS', 'CELL') LEFT JOIN 
    (SELECT DISTINCT PERSON_ID, SKILL_SHORT_DESC 
     FROM EPERSON.VIEW_UDRMS_PERSON_SKILL 
    ) SKILLS 
    ON SKILLS.PERSON_ID = PERSON.PERSON_ID 
GROUP BY PERSON.PERSON_ID, PERSON.FIRST_NAME, PERSON.MIDDLE_NAME, PERSON.LAST_NAME, PERSON.USER_NAME 
+0

似乎是從[這個問題]的後續(http://stackoverflow.com/questions/38513561/oracle-select-query-for-one-to-many-relationship-between-two-tables/38516352 #385163520)。 – Unoembre

+0

在連接之前(而不是DISTINCT)在派生表中執行LISTAGG,並且對於MAX(CASE)也是類似的。 – dnoeth

回答

0

你可能之前做一個早期聚集,即總的加入:

SELECT PERSON.PERSON_ID, 
    PERSON.FIRST_NAME, 
    PERSON.MIDDLE_NAME, 
    PERSON.LAST_NAME, 
    PERSON.USER_NAME, 

    PHONE.HOME_PHONE, 
    PHONE.BUSINESS_PHONE, 
    PHONE.CELL_PHONE, 

    SKILLS.Speciality 

FROM VIEW_PERSON PERSON 

INNER JOIN 
(
    SELECT PERSON_ID, 
     MAX(CASE WHEN PHONE_TYPE = 'HOME' THEN PHONE_NUMBER end) AS HOME_PHONE, 
     MAX(CASE WHEN PHONE_TYP= 'BUSINESS' THEN PHONE_NUMBER end) AS BUSINESS_PHONE, 
     MAX(CASE WHEN PHONE_TYP= 'CELL' THEN PHONE_NUMBER end) AS CELL_PHONE 
    FROM VIEW_PHONE 
) PHONE 
ON PHONE.PERSON_ID = PERSON.PERSON_ID 

LEFT JOIN 
(
    SELECT PERSON_ID, 
     LISTAGG(CASE 
       WHEN SKILL_DESC = '1' THEN '1:1' 
       WHEN SKILL_DESC = '2' THEN '2:2' 
       WHEN SKILL_DESC = '3' THEN '3:3' 
       WHEN SKILL_DESC = '4' THEN '4:4' 
       ELSE '' 
       end, ',') 
     WITHIN GROUP (ORDER BY SKILL_SHORT_DESC) AS Speciality 
    FROM EPERSON.VIEW_UDRMS_PERSON_SKILL 
    GROUP BY PERSON_ID 
) SKILLS 
ON SKILLS.PERSON_ID = PERSON.PERSON_ID 

這可能是更有效,也因爲行數是在連接前減少。

+0

嗨,我無法在TOAD中完成這項工作。我還在LISTAGG和TOAD內部有一個'AND PERSON.PERSON_DEPT = .....',即使它在FROM子句中定義,PERSON也是一個無效標識符。我刪除了PERSON.DEPT,TOAD仍然抱怨SELECT PERSON_ID在LEFT JOIN之後說不是一個單獨的組功能 – John

+0

那麼,必須刪除'SKILLS.'限定符並且缺少'GROUP BY',我會修復我的答案。但是當你需要訪問PERSON中的一列時,你不能使用這種方法。 – dnoeth

0

試試這個:

SELECT PERSON_ID, 
    FIRST_NAME, 
    MIDDLE_NAME, 
    LAST_NAME, 
    USER_NAME, 
    home, 
    business, 
    cell, 
    listagg(speciality,',') within GROUP(
ORDER BY 1) speciality 
FROM 
    (SELECT * FROM 
(
SELECT PERSON.PERSON_ID, PERSON.FIRST_NAME, PERSON.MIDDLE_NAME, PERSON.LAST_NAME,  
     PERSON.USER_NAME,phone_type, 
     PHONE_NUMBER, 
     case when SKILLS.SKILL_SHORT_DESC = '1' then '1:1' 
        when SKILLS.SKILL_SHORT_DESC = '2' then '2:2' 
        when SKILLS.SKILL_SHORT_DESC = '3' then '3:3' 
        when SKILLS.SKILL_SHORT_DESC = '4' then '4:4' 
    when SKILL_SHORT_DESC = 'ADMIN' AND PERSON.DEPT= 'DEPT1' then 'DEPT1:ADMIN' 
    when SKILL_SHORT_DESC = 'ADMIN' AND PERSON.DEPT= 'DEPT2' then 'DEPT2:ADMIN' 
        else '' 
       end AS Speciality 
FROM VIEW_PERSON PERSON INNER JOIN 
    (SELECT DISTINCT PERSON_ID, PHONE_TYPE, PHONE_NUMBER FROM VIEW_PHONE 
    ) PHONE 
    ON PHONE.PERSON_ID = PERSON.PERSON_ID AND PHONE.PHONE_TYPE in ('HOME', 'BUSINESS', 'CELL') LEFT JOIN 
    (SELECT DISTINCT PERSON_ID, SKILL_SHORT_DESC 
     FROM VIEW_UDRMS_PERSON_SKILL 
    ) SKILLS 
    ON SKILLS.PERSON_ID = PERSON.PERSON_ID 
) 
pivot (MAX(phone_number) FOR(phone_type) IN ('HOME' 
AS 
    HOME,'BUSINESS' 
AS 
    BUSINESS, 'CELL' 
AS 
    CELL))) group by PERSON_ID, FIRST_NAME, MIDDLE_NAME, LAST_NAME, USER_NAME, home, cell, business; 

給出:

1 guru   guru 111-111-1111 111-444-1111 111-333-1111 1:1,2:2,3:3 

用途 'PIVOT'。