2017-02-14 9 views
2

今日、私は友人から問題が発生しました。条件を使用して重複を削除します

問題 - 重複を排除するためにwhere句を使用するUNION ALL(notion)を使用してSQLクエリを作成します。

  • 私はユニークな、明確なキーワードを使用することはできません表現
  • でグループを使用することはできません。

入力 -

id(Table 1) 
1 
2 

fk_id(Table 2) 
1 
1 
2 

私は彼にユニークなIDを生成しているクエリ

select id from 
(
select id , row_number() over(partition by id order by id) rn from 
(
select id from T1 
union all 
select fk_ID id from T2 
) 
)where rn = 1; 

Output - 
id 
1 
2 

以下の溶液を得ました。

彼のサスペンスは、私もrow_number()を使用することはできません。私はちょうど条件を使用する必要があります。私はOracleデータベースにクエリを書いています。

お勧めします。

ありがとうございます。

+0

:(。あなたはt2に重複値が存在しないことを示しているように、このアプローチは、その後動作しない)ここでは、t1値を参照していないt1プラス一意の値からt2から、ユニークな値のためのクエリですおそらく実用的でないかもしれない学問的質問。 –

+0

row_number()を使用できないのはなぜですか? – BobC

+0

@BobC質問によると、私はwhere節を使って目的の結果を得るだけです。提案してください。 – Tajinder

答えて

4

名前とデータから、表t1idは一意であると見なすことができます。

表示されている名前とデータから、t2fk_idtable1.idの外部キーであると仮定できます。

したがって、2つのテーブルのIDの和集合は、単にテーブルt1にあるIDです。

select id from t1 
union all 
select fk_id from t2 where 1 = 2; 

t2.fk_idt1.idを参照する外部キーでなかった場合、我々はNOT EXISTSを使用します。我々は、しかし、二つのテーブルの上にUNION ALLを使用するように強制されたよう

は、我々は何を追加することなく、すべての疑似UNIONを使用することができます代わりにwhere句にNOT INと入力します。ただし、重複なしで結果を返す場合は、t2に重複がなくてはならない。

興味深い
select id from t1 
union all 
select fk_id from t2 where fk_id not in (select id from t1); 
+0

ありがとう、素晴らしい人。 – Tajinder

+0

テーブルの間にプライマリの外部キーの関係がない場合は、クエリを記述できますか? – Tajinder

+0

このクエリはあなたの場合でも動作します。彼らのプライマリと外部キーがない場合 –

2

さらに一般的なケースでは、両方のテーブルに重複がある場合があります。

テストデータ:

create table table1(id) as ( 
    select 1 from dual union all 
    select 1 from dual union all 
    select 2 from dual union all 
    select 2 from dual union all 
    select 1 from dual 
) 

create table table2(fk_id) as (
    select 1 from dual union all 
    select 1 from dual union all 
    select 1 from dual union all 
    select 3 from dual union all 
    select 4 from dual union all 
    select 1 from dual union all 
    select 4 from dual union all 
    select 2 from dual 
) 

クエリ:

with tab1_union_all_tab2 as ( 
    select 'tab1'||rownum as uniqueId, id from table1 UNION ALL 
    select 'tab2'||rownum   , fk_id from table2 
)  
select id 
from tab1_union_all_tab2 u1 
where not exists (select 1 
        from tab1_union_all_tab2 u2 
        where u1.id = u2.id 
        and u1.uniqueId < u2.uniqueId 
       ) 

結果:

ID 
---------- 
     3 
     4 
     1 
     2 

これは、私を明確にすべき背後DEA:として正しくトルステンケトナーによって観察

with tab1_union_all_tab2 as ( 
    select 'tab1'||rownum as uniqueId, id from table1 UNION ALL 
    select 'tab2'||rownum   , fk_id from table2 
)  
select uniqueId, id, 
     (select nvl(listagg (uniqueId, ', ') within group (order by uniqueId), 'NO DUPLICATES') 
      from tab1_union_all_tab2 u2 
     where u1.id = u2.id 
      and u1.uniqueId < u2.uniqueId 
     ) duplicates 
from tab1_union_all_tab2 u1 

UNIQUEID   ID DUPLICATES 
---------- ---------- -------------------------------------------------- 
tab11    1 tab12, tab15, tab21, tab22, tab23, tab26 
tab12    1 tab15, tab21, tab22, tab23, tab26 
tab13    2 tab14, tab28 
tab14    2 tab28 
tab15    1 tab21, tab22, tab23, tab26 
tab21    1 tab22, tab23, tab26 
tab22    1 tab23, tab26 
tab23    1 tab26 
tab24    3 NO DUPLICATES 
tab25    4 tab27 
tab26    1 NO DUPLICATES 
tab27    4 NO DUPLICATES 
tab28    2 NO DUPLICATES 

、あなたは簡単に文字列とrownumを連結することで代わりに一意のIDを構築するのrowidを使用するために、これを編集することができます。

with tab1_union_all_tab2 as ( 
    select rowid uniqueId, id from table1 UNION ALL 
    select rowid   , fk_id from table2 
)  
select id 
from tab1_union_all_tab2 u1 
where not exists (select 1 
        from tab1_union_all_tab2 u2 
        where u1.id = u2.id 
        and u1.uniqueId < u2.uniqueId 
       ) 
+0

の質問を得ました。これは素晴らしい解決策です。両方のテーブルで重複している可能性のある値でも作業します。 (同じことは単にOracleの 'ROWID'を使って同じことができますので、あなた自身で独自の行IDを生成する必要はありません)。答えは、クエリが何をしているのかあなたはこのアプローチを決めました。私の+1。 –

+0

@Aleksejあなたの努力に感謝します。 – Tajinder

1

書き込みA声明2番目の選択では、すべてのid = = fk_id

関連する問題