2009-10-20 8 views
10

私は2つの選択肢を持っており、それらを組み合わせて両方の選択肢でユニークな行だけが返されるようにしたいと思います。これを実現するためのOracle 10gに組み込まれている方法はありますか?OracleのINTERSECTの反対

 
(select1 UNION select2) 
MINUS 
(select1 INTERSECT select2) 

が、私はそれを避けたい:

は、私はこのような何かを行うことができます知っています。 select1select2の両方に20行ありますので、この方法はあいまいで維持しにくいでしょう。

+1

この演算子の名前は、「対称差」である - これで、Googleは結果の数(すべてはこれが高速であることを行っていないであることを示唆している傾向にあるWICH)を与えます。 – AakashM

+0

これは遅い場合は、私にとっては問題ではありません。これは私の個人的な使用のためのバッチスクリプトであり、それを超効率的にする必要はありません。 –

+0

2つの選択肢はどのように見えますか?それらを変更して、選択を1つだけ実行して最終的な結果を得ることができます。 –

答えて

8

select1select2の両方には、重複を返さない場合は、このようなものを使用することができます

SELECT * FROM (select1 UNION ALL select2) a 
GROUP BY a.col1, a.col2, ... 
HAVING count(*) = 1 
1

ここでは別の考えです:

  • 完全外部SELECT1とSELECT2
  • 使用の参加くださいをselect1.id = NULL(レコードはselect2のみ)またはselect2.ID = NULL(レコードはselect1のみ)のレコードのみ
このような

:私はそれを行う

SELECT * 
FROM select1 FULL OUTER JOIN select2 on select1.id = select2.id 
WHERE select1.id is null or select2.id is null 
0
-- get not intersect data 
SELECT_FINAL 
WHERE FIELD_PK IS NOT IN(
    -- get ids of intersect 
    SELECT_AUX FIELD_PK1 FROM (
     SELECT1 
     INTERSECT 
     SELECT2 
    ) 
) 

1

これはME-ないそれがどのように速く確実に働きました。

(select table_name from dba_tables where user = 'X' 
union 
select table_name from dba_tables where user = 'Y') 
minus 
(select table_name from dba_tables where user = 'X' 
intersect 
select table_name from dba_tables where user = 'Y') 
3

Oracle 10gでは、共通テーブル式を自由に使用できます。

WITH 
    select_1 AS (
    SELECT * 
    FROM your_table 
    WHERE your_condition = 1 
), 
    select_2 AS (
    SELECT * 
    FROM your_other_table 
    WHERE your_other_condition = 1 
) 
SELECT * FROM select_1 
UNION 
SELECT * FROM select_2 
MINUS 
(
    SELECT * FROM select_1 
    INTERSECT 
    SELECT * FROM select_2 
); 

これは、サブクエリをメンテナンス可能にし、最終クエリの目的をクリアします。もちろん

、OracleはSQLにSYM_DIFFERENCE演算子を追加持つことはさらに良くなるだろうが、—が、彼らはまだBOOLEANデータ型が良いでしょう納得していないなら、私は自分の息を保持していませんよ。

0

今度はcount()アナリティック(Oracle 10以降)を使用する別の解決方法があります。

利点:

  • 我々は(この例では例えばKK1、KK2)にEXTRASECTする列を指定することができます。
  • マッチする必要のない非キー列(例ではNK1、NK2 ...)を選択できます。
  • 効率的な計画。
  • FULL OUTER JOINの例と似ていますが、キー列をデコードまたはケースを必要とする別々のフィールドとして取得することはありません。

select KK1, KK2, NK1, NK2 from (select KK1, KK2, NK1, NK2, count(*) over(partition by KK1, KK2) cnt from (select KK1, KK2, NK1, NK2 from X union all select KK1, KK2, NK1, NK2 from Y)) where cnt = 1;