Oracle从许多JOIN中选择一对多返回的重复项

时间:2016-07-22 15:06:19

标签: sql oracle

我正在学习Oracle SQL并且遇到了当前查询的问题。我正在使用几个VIEW,其中一些是一对多的关系。

我让LISTAGG查询正常工作,这很好。

现在,我在我的查询中添加了一个到多个VIEW_PHONE。

我试着看着PIVOT,但我有点失落。我使用Max,Case找到了这个查询,它本身就可以工作。当我合并

的Phone 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(' HOME',' BUSINESS' CELL')更改为PHONE.PHONE_TYPE(& #39; HOME'),它只会提供一个技能字符串而不是3.因为我试图获取3个电话号码,它正在影响我与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

2 个答案:

答案 0 :(得分: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

这也可能更有效,因为在连接之前减少了行数。

答案 1 :(得分: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'。