我需要同步两个表。我们假设这些表包含以下列:
Table1: A, B, C, D
Table2: A, B, C, E
我需要在Table1中找到这样的行,表2中没有对应(A, B, C)
值的条目,然后将E计算为F(D)并更新Table2。
如果我需要匹配,例如只有A,我会写下面的查询:
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)
编写此类查询的最佳方法是什么?
答案 0 :(得分:20)
如果两个表中的(a,b,c)都是非空的,那么NOT IN和NOT EXISTS很可能(在我试过的验证中)生成相同的执行计划。
如果(a,b,c)被声明为可空,但是你知道这些列实际上不是空的,你可以通过添加“欺骗优化器来进行散列反连接”和a不为空,并且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)
答案 1 :(得分:6)
SELECT * FROM Table1
WHERE (A, B, C) NOT IN
(SELECT A,B,C FROM Table2)
答案 2 :(得分:0)
SELECT * FROM Table1
WHERE
not exist (
SELECT 1 FROM Table2
where Table2.a=Table1.a
and Table2.b=Table1.b
and Table2.c=Table1.c )
编辑:注意不存在和NOT IN在某些情况下不完全相同(NULL值) 见:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:442029737684
答案 3 :(得分: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发布。它执行散列连接反并避免过滤。
或尝试
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快得多。
答案 4 :(得分:0)
一个小附录:我发现当NOT IN子句包含多个列时,Oracle(我的情况下为11gR1)拒绝散列反连接,例如,
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
)
这甚至在添加其中一个提示(与UNNEST
相同)和非NULL条件时也是如此。只有一列它可以工作。
答案 5 :(得分:0)
出于性能原因,从不这样做
NOT IN (SELECT
使用
NOT EXISTS (SELECT 1 FROM