2010-12-03 18 views
6

2つのテーブルを同期させる必要があります。さんは、テーブルには、次の列が含まれていると仮定しよう:Oracle:複数の列で高速に入力しない

Table1: A, B, C, D 
Table2: A, B, C, E 

私はその後、(D)FとしてEを計算し、表2を更新し、表2に(A, B, C)値を対応するエントリが存在しないことを表1にこのような行を見つける必要があります。

たとえば、唯一、私は次のクエリを記述します。

SELECT * FROM Table1 WHERE A NOT IN (SELECT A FROM Table2) 

マルチコラムアナログは遅すぎるように思わ:

SELECT * FROM Table1 WHERE A NOT IN (SELECT A FROM Table2) 
         AND B NOT IN (SELECT B FROM Table2) 
         AND C NOT IN (SELECT C FROM Table2) 

、このようなクエリを記述するための最良の方法は何ですか?

答えて

18

両方のテーブルで(a、b、c)がNOT NULLの場合、NOT INとNOT EXISTSの両方が同じ実行計画を生成する可能性が高くなります。

(a、b、c)がNULL可能であると宣言されているが、が実際にはNULLでないことがわかっている場合は、オプティマイザをトリックして、 "AND a is notヌルであり、bはヌルではなく、cはヌルではありません。 (。あなたはまた、サブクエリに/ * + HASH_AJ * /ヒントを追加する必要があります)

はまた、次のクエリは同じではありません:

from table1 
where (a,b,c) not in (select a,b,c from table2) 

from table1 
where a not in(select a from table2) 
    and b not in(select b from table2) 
    and c not in(select c from table2) 
5
SELECT * FROM Table1 
    WHERE (A, B, C) NOT IN 
    (SELECT A,B,C FROM Table2) 
+0

これは最適なソリューションではありません。 – erbsock

+1

は、カラムa、b、cにはNULL値がない必要がありますが(NULLがある場合は、誤った答えがあります)、最適な解決策になります。 @erbsock:列がNOT NULLと宣言されている場合、オプティマイザは最も効率的なパス(ANTI-HASH JOIN ...)を使用できます。 –

+0

@Vincent:11gと仮定していますか? – erbsock

0

投稿としてあなたは

SELECT * FROM Table1 
WHERE 
not exists (
    SELECT 1 FROM Table2 
    where Table2.a=Table1.a 
    and Table2.b=Table1.b 
    and Table2.c=Table1.c); 

を試すことができます〜によってguigui42。これは、ハッシュ結合を防止し、フィルタを回避します。

OR外部結合+フィルターを行い

select t1.* 
from table1 t1, table2 t2 
where t1.a = t2.a(+) 
and t1.b = t2.b(+) 
and t1.c = t2.c(+) 
and (t2.a is null or t2.b is null or t2.c is null); 

を試してみてください。どちらの方法もNOT INを行うよりもずっと速くすべきです。

0

小さな補遺:私が見つけたオラクル(私の場合は11gR1のは)(UNNESTと同じ)ヒントの一つと非を追加する抗NOTは、句に複数の列、例えば、

SELECT * FROM Table1 WHERE (A,B,C) NOT IN (
    SELECT /*+ HASH_AJ */ A,B,C FROM Table2 
     WHERE A IS NOT NULL AND B IS NOT NULL AND C IS NOT NULL 
) 

、これが含まれている場合に参加する場合でも、ハッシュを拒否していること-NULL条件イオン。 1つの列だけで動作します。

関連する問題