EXISTS子句

上一篇 / 下一篇  2008-06-10 19:09:47

1 exists
SELECT * FROM anken_m WHERE EXISTS(
SELECT my_list_temp_m.sales_code
FROM my_list_temp_m
WHERE my_list_temp_m.sales_code=anken_m.sales_code)
说明:
1) 查询在anken_m表和my_list_temp_m表中都存在的sales_code。
2) sales_code是anken_m的主键,my_list_temp_m的外键。
注意:
1) 外层查询表anken_m是查询的对象。
2) 内层查询表my_list_temp_m是条件对象。
3) 内外层的查询表不能相同。
4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。
5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。


2 not exists
SELECT * FROM anken_m WHERE NOT EXISTS(
SELECT my_list_temp_m.sales_code
FROM my_list_temp_m
WHERE my_list_temp_m.sales_code=anken_m.sales_code)
说明:
1) 查询在anken_m表中存在,但是在my_list_temp_m表中不存在的sales_code。
2) sales_code是anken_m的主键,my_list_temp_m的外键。
注意:
1) 外层查询表anken_m是查询的对象。
2) 内层查询表my_list_temp_m是条件对象。
3) 内外层的查询表不能相同。
4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。
5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。


3 综合运用
UPDATE anken_m SET(plan_type_code, branch_name, business_type_code) =(SELECT anken.plan_type_code,anken.branch_name,anken.business_type_code FROM anken WHERE anken.sales_code=anken_m.sales_code)
WHERE EXISTS ( SELECT anken.sales_code FROM anken,my_list_temp_m
WHERE my_list_temp_m.sales_code=anken.sales_code
AND anken.sales_code=anken_m.sales_code )
说明:
1) 用一个表的记录数据更新另一个表的记录数据。
2) 用一个SQL语句进行批量更新。
2) sales_code是anken,anken_m的主键,my_list_temp_m的外键。
注意:
1) set 语句中的要被更新字段必须跟数据源字段一一对应,另外数据源查询中的条件必须限定一条记录。也就是根据sales_code可以唯一确定anken的一条记录,和anken_m的一条记录,这样才能保证要被更新的记录和数据源记录的主键是相同的。
2) 根据WHERE EXISTS语句可以确定数据源记录的范围,也就是可以用anken表中哪些记录更新anken_m表。所以anken_m不需要在WHERE EXISTS语句中的FROM后添加。

除了这个还找到:
不是每个在你身上拉屎的都是你的敌人


   一只小鸟正在飞往南方过冬的途中。天气太冷了,小鸟冻僵了,从天上掉下来,跌在一大片农田里。它躺在田里的时候,一只母牛走了过来,而且拉了一泡屎在它身上。冻僵的小鸟躺在牛屎堆里,发掘牛粪真是太温暖了。牛粪让它慢慢缓过劲儿来了!它躺在那儿,又暖和又开心,不久就开始高兴地唱起歌来了。一只路过的猫听到了小鸟的歌声,走过来查个究竟。顺着声音,猫发现了躲在牛粪中的小鸟,非常敏捷地将它刨了出来,并将它给吃了!

  这个故事的寓意是……

  1) 不是每个在你身上拉屎的都是你的敌人。

  2) 不是每个把你从屎堆中拉出来的都是你的朋友。

  3) 而且,当你陷入深深的屎堆当中(身陷困境)的时候,闭上你的鸟嘴!

TAG:

OFFICE精英俱乐部(赏四季花开,听世间风雨) 引用 删除 晓芳   /   2008-07-22 10:48:46
IN&EXISTS 与 NOT IN&NOT EXISTS
EXISTS的执行流程
select * from t1 where exists ( select null from t2 where y = x )
可以理解为:
for x in ( select * from t1 )
loop
   if ( exists ( select null from t2 where y = x.x )
   then
      OUTPUT THE RECORD
   end if
end loop
对于in 和 exists的性能区别:
如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in,反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。
其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了
                        
另外IN时不对NULL进行处理
如:
select 1 from dual where null   in (0,1,2,null)
为空
2.NOT IN 与NOT EXISTS:
NOT EXISTS的执行流程
select .....
   from rollup R
where not exists ( select 'Found' from title T
                            where R.source_id = T.Title_ID);
可以理解为:
for x in ( select * from rollup )
   loop
      if ( not exists ( that query ) ) then
                OUTPUT
      end if;
   end;

注意:NOT EXISTS 与 NOT IN 不能完全互相替换,看具体的需求。如果选择的列可以为空,则不能被替换。

例如下面语句,看他们的区别:
select x,y from t;
x              y
------       ------
1              3
3 1
1 2
1 1
3 1
5
select * from t where   x not in (select y from t t2   )
no rows

select * from t where   not exists (select null from t t2
                                                 where t2.y=t.x )
x    y
------   ------
5    NULL
所以要具体需求来决定

对于not in 和 not exists的性能区别:
not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,并使用anti hash join.
如果主查询表中记录少,子查询表中记录多,并有索引,可以使用not exists,另外not in最好也可以用/*+ HASH_AJ */或者外连接+is null
NOT IN 在基于成本的应用中较好

比如:
select .....
from rollup R
where not exists ( select 'Found' from title T
                        where R.source_id = T.Title_ID);

改成(佳)

select ......
from title T, rollup R
where R.source_id = T.Title_id(+)
and T.Title_id is null;
                              
或者(佳)
sql> select /*+ HASH_AJ */ ...
       from rollup R
       where ource_id NOT IN ( select ource_id
                                              from title T
                                          where ource_id IS NOT NULL )


//------------------------http://blog.csdn.net/aiunong/archive/2006/02/22/606194.aspx

讨论IN和EXISTS。
    select * from t1 where x in ( select y from t2 )
    事实上可以理解为:
    select *
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;
    ——如果你有一定的SQL优化经验,从这句很自然的可以想到t2绝对不能是个大表,因为需要对t2进行全表的“唯一排序”,如果t2很大这个排序的性能是 不可忍受的。但是t1可以很大,为什么呢?最通俗的理解就是因为t1.x=t2.y可以走索引。但这并不是一个很好的解释。试想,如果t1.x和t2.y 都有索引,我们知道索引是种有序的结构,因此t1和t2之间最佳的方案是走merge join。另外,如果t2.y上有索引,对t2的排序性能也有很大提高。
    select * from t1 where exists ( select null from t2 where y = x )
    可以理解为:
    for x in ( select * from t1 )
    loop
       if ( exists ( select null from t2 where y = x.x )
       then
          OUTPUT THE RECORD!
       end if
    end loop
    ——这个更容易理解,t1永远是个表扫描!因此t1绝对不能是个大表,而t2可以很大,因为y=x.x可以走t2.y的索引。
    综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

我们要根据实际的情况做相应的优化,不能绝对的说谁的效率高谁的效率低,所有的事都是相对的
OFFICE精英俱乐部(赏四季花开,听世间风雨) 引用 删除 晓芳   /   2008-07-22 10:46:48
SQL-如何提高select语句的效率 (转载)
1.使用exists关键字检查结果集:不要用count(*)来检查结果集中是否包含行。
2.使用标准联接代替嵌套查询:在执行嵌套查询时,SQL server将先执行内部的子查询,然后将查询结果返回给外部查询的作为检索的数据源,最后执行外部的主查询。而在执行包含标准联接的查询时,SQL server将要执行的仅仅是一个查询。
3.有效避免整表扫描,使用索引。
4.在like子句的匹配条件的开始使用了%,若在like子句的匹配条件的开始使用了%,那么包含这个like分句的查询将会调用整表扫描。


视图(view)和select 语句效率
同志们。我再一次用事实来证明一下sql中的view和select语句那个好。。。
首先我要说一个前提,就是建view的语句和select语句的效率是一样的,你不要拿一个效率很差的语句去建个视图,然后在弄个优化过的sql语句去直接select;那样结果只有一个肯定是select语句效率好。
我测试一下,可以很肯定告诉各位view比select语句效率要高,而且要高很多;
建立一个view关联了8个表,搜索的数据1300+条记录,因为记录比较少,所以我重复执行了一下,重复执行了17次:
结果view的耗时:2200毫秒左右(因为执行了多次取得平均值)
select耗时:3550毫秒左右(平均值)
我的view中的select和直接执行的select是一样的。大家也可以试试,有问题可以讨论。
哦,说一下我的测试环境是公司的服务器,os:win2003;内存:4GB;cpu:双至强cpu;数据库:sql server 2005
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-08-20  
     12
3456789
10111213141516
17181920212223
24252627282930
31      

数据统计

  • 访问量: 6717
  • 日志数: 39
  • 图片数: 2
  • 建立时间: 2006-12-31
  • 更新时间: 2008-07-26

RSS订阅

Open Toolbar