数据库sql语句的exists总结 sql exists in 学习

先来比较下语法:

--deals=交易表,areas=地域表,例如香港;我们的目的:查看有交易的地域

select * from areas where id in (select city_id from deals);

select * from areas where id in   (select city_id from deals where deals.city_id = areas.id);

select * from areas where exists (select null     from deals where deals.city_id = areas.id);

区别:

EXISTS语法并没有说哪个字段落在了子查寻的结果中,而是说exists后面的语句执行的结果是不是有记录,只要有记录,则主查询语句就成立。它代表‘存在’,用来引领嵌套查询的子查询,它不返回任何数据,只产生逻辑真值‘true’与逻辑假值‘False’。由EXISTS引出的子查询,其目标列表达式通常都用*(用null也可以),因为带有EXISTS的子查询只返回真值或假值,给出列名没有实际意义。

性能变化的关键:
#1 执行的先后顺序
谁是驱动表,谁先执行查询,谁后执行查询
#2 执行过程
exists的优点是:只要存在就返回了,这样的话很有可能不需要扫描整个表。  
in需要扫描完整个表,并返回结果。
所以,在字表比较小的情况下,扫描全表和部分表基本没有差别;但在大表情况下,exists就会有优势。
看这两个语句:
--子查询会执行完全关联,并返回所有符合条件的city_id

select * from areas where id in   (select city_id from deals where deals.city_id = areas.id);

--子查询的关联其实是一样的,但子查询只要查到一个结果,就返回了,所以效率还是比较高些的

select * from areas where exists (select null     from deals where deals.city_id = areas.id);

#3 字表查询的结果
exists判断子查询的结果是不是存在,但查到什么结果,什么字段,并不关心;
in      需要子查询查得的结果给主查询使用
in 和 Exists的用法区别
1.
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
对于inexists的性能区别:
   如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in,反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists
   其实我们区分inexists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是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 )

问题和解决

问题1:

--users表有1000条记录,id自增,id都大于0

select * from users where exists (select * from users limit 0); --输出多少条记录?

select * from users where exists (select * from users where id < 0); --输出多少条记录?

答案(请选中查看):

10000条

0条

原因:

exists查询的本质,只要碰到有记录,则返回true;所以limit根本就不会去管,或者说执行不到。

问题2:

exists可以完全代替in吗?

不能。

例如:

--没有关联字段的情况:枚举常量

select * from areas where id in (4, 5, 6);

--没有关联字段的情况:这样exists对子查询,要么全true,要么全false

select * from areas where id in (select city_id from deals where deals.name = 'xxx');

举个相关exists的sql优化例子:

9、用exists替代in(发现好多程序员不知道这个怎么用): 
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。 
在这种情况下,使用exists(或not exists)通常将提高查询的效率。 
举例: 
(低效) 
select ... from table1 t1 where t1.id > 10 and pno in (select no from table2 where name like 'www%'); 
(高效) 
select ... from table1 t1 where t1.id > 10 and exists (select 1 from table2 t2 where t1.pno = t2.no and name like 'www%'); 
10、用not exists替代not in: 
在子查询中,not in子句将执行一个内部的排序和合并。 
无论在哪种情况下,not in都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。 
为了避免使用not in,我们可以把它改写成外连接(Outer Joins)或not exists。 
11、用exists替换distinct: 
当提交一个包含一对多表信息的查询时,避免在select子句中使用distinct. 一般可以考虑用exists替换 
举例: 
(低效) 
select distinct d.dept_no, d.dept_name from t_dept d, t_emp e where d.dept_no = e.dept_no; 
(高效) 
select d.dept_no, d.dept_name from t_dept d where exists (select 1 from t_emp where d.dept_no = e.dept_no); 
exists使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 
12、用表连接替换exists: 
通常来说,采用表连接的方式比exists更有效率。 
举例: 
(低效) 
select ename from emp e where exists (select 1 from dept where dept_no = e.dept_no and dept_cat = 'W'); 
SELECT ENAME 
(高效) 
select ename from dept d, emp e where e.dept_no = d.dept_no and dept_cat = 'W';

R

R

R

+

R

R

R

数据库——SQL中EXISTS怎么用2(转)的更多相关文章

  1. 数据库——SQL中EXISTS怎么用3(转)

    有一个查询如下: 1 SELECT c.CustomerId, CompanyName   2 FROM Customers c   3 WHERE EXISTS(   4     SELECT Or ...

  2. 数据库——SQL中EXISTS怎么用1(转)

    EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 方法/步骤   EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返 ...

  3. sql 中 exists用法

    SQL中EXISTS的用法   比如在Northwind数据库中有一个查询为SELECT c.CustomerId,CompanyName FROM Customers cWHERE EXISTS(S ...

  4. SQL中EXISTS怎么用[转]

    SQL中EXISTS怎么用 1 2 3 4 分步阅读 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 方法/步骤 1 EXISTS用于 ...

  5. SQL中EXISTS和IN用法

    SQL中EXISTS的用法  指定一个子查询,检测行的存在. 语法:EXISTS subquery 参数:subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INT ...

  6. sql中exists和not exists的用法

    该文转载自:http://www.cnblogs.com/mytechblog/articles/2105785.html sql中exists,not exists的用法 exists : 强调的是 ...

  7. 十、SQL中EXISTS的用法 十三、sql server not exists

    十.SQL中EXISTS的用法 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False EXISTS 指定一个子查询,检测 行 的存在. 语法 ...

  8. 数据库SQL中case when函数的用法

    Case具有两种格式,简单Case函数和Case搜索函数.这两种方式,可以实现相同的功能.简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式. 简单Cas ...

  9. sql中exists和notexists用法总结(并和in的比较)

    首先头脑中有三点概念: 1.EXISTS子查询找到的提交 NOT EXISTS 子查询中 找不到的提交 说明:不要去翻译为存在和不存在,把脑袋搞晕. 2.建立程序循环的概念,这是一个动态的查询过程.如 ...

随机推荐

  1. Oracle LISTENER 主机名修改为IP地址后LISTENER无法监听到实例 oracle监听错误与hosts文件配置

    为什么listener.ora文件里面HOST后面到底应该输入IP地址还是主机名.我的经验告诉我,这边最好使用主机名.很多的时候,一个机器绑定的不只一个IP地址,如HOST后面是IP地址,那么ORAC ...

  2. 【LeetCode】154. Find Minimum in Rotated Sorted Array II (3 solutions)

    Find Minimum in Rotated Sorted Array II Follow up for "Find Minimum in Rotated Sorted Array&quo ...

  3. SolrCloud之分布式索引及与Zookeeper的集成--转载

    原文地址:http://josh-persistence.iteye.com/blog/2234411 一.概述 Lucene是一个Java语言编写的利用倒排原理实现的文本检索类库,Solr是以Luc ...

  4. ASP.NET MVC下的异步Action的定义和执行原理[转]

    http://www.cnblogs.com/artech/archive/2012/06/20/async-action-in-mvc.html Visual Studio提供的Controller ...

  5. Python学习笔记011——内置函数eval()

    1 描述 eval()  函数用来执行一个字符串表达式,并返回表达式的值 2 语法 原文 eval(expression[, globals=None[, locals=None]]) express ...

  6. Android 轻松实现语音识别

      2010-11-12 17:01:51 标签:休闲 职场 Android 语音识别 移动开发 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任 ...

  7. 竞态条件与sigsuspend函数

    一.利用pause和alarm函数实现sleep函数 #include <unistd.h> int pause(void); pause函数使调用进程挂起直到有信号递达.如果信号的处理动 ...

  8. tmux安装

    安装tmux sudo yum -y install tmux 修改tmux配置 cat > /root/.tmux.conf <<EOF set-option -g default ...

  9. eclipse3.7之后,在引入的jquery的js文件打红叉

    使用Eclipse 3.7时,工程中加入jquery.xx.js文件,发现该文件出现错误提示(红×),但使用Eclipse 3.7以前的版本就不会出现这种提示.是因为Eclipse 3.7在.proj ...

  10. python 异步编程

    Python 3.5 协程究竟是个啥 Yushneng · Mar 10th, 2016 原文链接 : How the heck does async/await work in Python 3.5 ...