2017-10-17 1 views
0

나는 하나의 소스에 대한 ID 내의 모든 레코드를 다른 소스와 함께 가져와야하는 시나리오가 있습니다. 다음은 내 입력 레코드 집합입니다. 위의 기록에서그룹 오라클에 대한 쿼리

ID SOURCE CURR_FLAG  TYPE 
1 IBM  Y    P 
1 IBM  Y    OF 
1 IBM  Y    P 
2 IBM  Y    P 
2 TCS  Y    P 
3 IBM  NULL    P 
3 CTS  NULL    P 
3 TCS  NULL    P 
4 IBM  NULL    OF 
4 CTS  NULL    OF 
4 TCS  Y    ON 
5 CTS  NULL    OF 
5 TCS  Y    ON 

, 내가 IBM.Also과 함께 동일한 ID에 대해서도이 있어야합니다 같은 ID 그룹과 다른 소스에서 IBM과 같은 소스의 모든 레코드를 선택해야합니다, 우리는 가져 오기 위해 필요 curr_fl = 'Y'인 ID 그룹의 레코드가 하나 이상있는 레코드

ID = 1인데도 소스가 IBM이지만 다른 소스와 함께 특정 그룹에 레코드가없는 경우에도 해당 레코드가 있습니다. 그래서 우리는 그 신분증으로 그 기록을 가져 오면 안됩니다. 레코드 ID = 3에 대해 IBM이 다른 소스와 함께 소스를 가지고 있지만 CURR_FL = 'Y'인 레코드가 없으면 내 쿼리가 값을 가져 오지 않아야합니다. ID = 4 인 경우 모든 값을 가져올 수 있습니다 ID가 4 인 레코드는 값이 'Y'이고 IBM이 다른 소스와 결합한 것입니다. ID 5의 경우 해당 세트 내에 IBM 레코드 원본이 없으므로 가져 오면 안됩니다

또한 위의 조건을 만족시키는 그룹 내에서 유형에 대한 조건이 하나 더 필요합니다. P '가있는 레코드가 없으면 type ='OF 'else type ='ON '을 검색합니다.

내 기대되는 레코드 유형이'P '인 레코드가있는 경우 해당 레코드 만 가져와야합니다. 출력은 아래에 주어진다

ID SOURCE CURR_FLAG  TYPE 
2 IBM  Y    P 
2 TCS  Y    P 
4 IBM  NULL    OF 
4 CTS  NULL    OF 
4 TCS  Y    ON 

나는 아래와 같이 질의를 작성했다. 그러나 오랫동안 실행 중이며 결과를 가져 오지 않는다. id 초 동안 보면,

select 
    ID, 
    SOURCE, 
    CURR_FL, 
    TYPE 
from TABLE a where 
    exists(select 1 from TABLE B where a.ID=B.ID and a.rowid<>B.rowid and B.source<>a.source) 
    and exists(select 1 from TABLE C where a.ID=C.ID and C.source ='IBM') 
and exists(select 1 from TABLE D where a.ID=D.ID and D.CURR_FL='Y') and 
(TYPE,ID) IN (
select case type when 1 then 'P' when 2 then 'OF' else 'ON' END TYPE,ID from 
(select ID, 
    max(priority) keep (dense_rank first order by priority asc) as type 
     from (select ID,TYPE, 
       case TYPE 
        when 'P' then 1 
        when 'OF' then 2 
        when 'ON' then 3 
       end as priority 
      from TABLE where ID 
      in(select ID from TABLE where CURR_FL='Y') AND SOURCE='IBM' 
       ) 
       group by ID)) 

답변

0

먼저이 쿼리를 수정할 수있는 더 좋은 방법이 있나요. 내가 추천 :

select id 
from t 
group by id 
having min(source) <> max(source) and       -- at least two sources 
     sum(case when curr_flag = 'Y' then 1 else 0 end) > 0 and -- at least one Y 
     sum(case when source = 'IBM' then 1 else 0 end) > 0  -- IBM 

베이스 행을 얻으려면, 당신은 in, exists, 또는 join 사용할 수 있습니다

select t.* 
from t 
where id in (select id 
      from t 
      group by id 
      having min(source) <> max(source) and       -- at least two sources 
        sum(case when curr_flag = 'Y' then 1 else 0 end) > 0 and -- at least one Y 
        sum(case when source = 'IBM' then 1 else 0 end) > 0  -- IBM 
      ); 
0

당신이 그룹에서 IBM 적어도 하나의가 있음을 확인할 수 있습니다 분석 함수 사용을 그룹 내의 IBM과 별개로 적어도 하나의 다른 소스와 그룹 내의 Y가있는 최소한 하나의 플래그 :

with t(id, source, curr_flag, type) as 
(
    select 1, 'IBM', 'Y', 'P' from dual union all 
    select 1, 'IBM', 'Y', 'OF' from dual union all 
    select 1, 'IBM', 'Y', 'P' from dual union all 
    select 2, 'IBM', 'Y', 'P' from dual union all 
    select 2, 'TCS', 'Y', 'P' from dual union all 
    select 3, 'IBM', NULL, 'P' from dual union all 
    select 3, 'CTS', NULL, 'P' from dual union all 
    select 3, 'TCS', NULL, 'P' from dual union all 
    select 4, 'IBM', NULL, 'OF' from dual union all 
    select 4, 'CTS', NULL, 'OF' from dual union all 
    select 4, 'TCS', 'Y', 'ON' from dual union all 
    select 5, 'CTS', NULL, 'OF' from dual union all 
    select 5, 'TCS', 'Y', 'ON' from dual 
) 
select id, source, curr_flag, type 
    from (select id, source, curr_flag, type, 
       max(case when source = 'IBM' then 1 end) over (partition by id) ibm, 
       max(case when source != 'IBM' then 1 end) over (partition by id) not_ibm, 
       max(case when curr_flag = 'Y' then 1 end) over (partition by id) flag_y 
      from t) 
where ibm = 1 
    and not_ibm = 1 
    and flag_y = 1 
order by id, source;