今天有在****上查看一些关于NOT IN的效率优化,主要有参考
http://blog.****.net/anerou/article/details/5185573
对于下面一条sql
SELECT * FROM A WHERE A.ID NOT IN (SELECT B.ID FROM B)
优化方案有:
方法1:
select *
from emp a
where not exists ( select 1
from emp_bill b
where b.emp_no = a.emp_no)方法2:
select a.*
from emp a ,emp_bill b
where a.emp_no=b.emp_no(+)
and b.emp_no is null
实践中,方案1操作成功,没有问题。原博说方案2效率最高,但是我在尝试方案2时却遇到了问题。
A表 A_STS=Y 表示成功记录
ID | A_STS | VALUE |
---|---|---|
1 | Y | 1 |
2 | Y | 2 |
3 | Y | 2 |
4 | Y | 2 |
5 | 2 |
B表 B_STS=00 表示成功记录
ID | B_STS | VALUE |
---|---|---|
1 | 00 | 1 |
2 | 00 | 2 |
3 | 2 | |
4 | 00 | 2 |
5 | 5 |
要求查出A表中存在但B表中不存在的成功记录
SELECT * FROM A WHERE A.ID NOT IN (SELECT B.ID FROM B WHERE B.B_STS=’00’) AND A.A_STS=’Y’
两个表数据量均比较大,NOT IN跑哭了都没出结果。
于是我根据方法2写了下面一条sql,并很自然的加上了所需要的限制条件
select a.*
from A a ,B b
where a.id=b.id(+)
and b.id is null
and a.a_sts='Y'
and b._b_sts='00'
查询结果是 空
脑袋短路了很久,对几个条件分别注释后执行了几次
发现b.id is null 永远都不可能满足
其实最后的问题就是在 LEFT JOIN ON 与WHERE的优先级的问题,
我希望的结果是在成功记录中,筛选出B表中不存在的A表记录。而LEFT JOIN 是先关联,后滤表。
找到原因后,直接修改一下关联对象即可
select a.*
from A a ,(SELECT * FROM B WHERE B.B_STS=’00’) b
where a.id=b.id(+)
and b.id is null
and a.a_sts=’Y’
[基础问题,用得少想得少,也能坑死自己!]