2017-10-17 12 views
0

私は、1つのソースのID内のすべてのレコードを他のソースとともに取得する必要があるシナリオを持っています。私の入力したレコードセットは以下の通りです。上記の記録からグループoracleのクエリ

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などのソースを持つすべてのレコードを選択する必要があり、我々は唯一のフェッチする必要がありますそのIDグループ内の少なくとも1つのレコードがcurr_fl = 'Y'であるレコード

上記のシナリオでは、ID = 1のソースはIBMですが、その特定のグループにレコードがありません。そのIDでそのレコードを取得しないでください。 レコードID = 3の場合は、IBMと他のソースとの間にソースがありますが、CURR_FL = 'Y'のレコードがないため、クエリでは値を取得しません。ID = 4の場合、 ID = 4のレコードは、レコードの1つが値= 'Y'を持ち、IBMと他のソースとの組み合わせを持ちます。ID 5の場合は、そのレコード内にIBMレコードソースはありません。上記の条件を満たすグループ内でも、タイプの条件がもう1つ必要です。 Pのレコードがない場合は、type = 'OF' else type = 'ON'を検索します。

私の予想出力は以下に与えられます

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 

私は以下のようにクエリを書いています。しかし、それは長い間実行されており、結果をフェッチしていません。このクエリを変更するより良い方法はありますか?

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

まず、idを探します。私が推薦する:

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 

をベース行を取得するには、あなたがinexists、または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とは別の少なくとも1つの他のソース、およびグループ内のYを持つ少なくとも1つのフラグ:

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;