`
fantaxy025025
  • 浏览: 1251495 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

数据库sql语句的exists总结

 
阅读更多

数据库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 INNOT 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



分享到:
评论

相关推荐

    Oracle数据库SQL语句优化策略

    基本的Sql编写注意事项 尽量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替 用IN写出来的SQL的优点是比较容易写及清晰易懂,但是用IN的SQL性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的...

    SQL语句集锦.rar

    动态SQL语句.txt 动态语句.txt 区分大小写.txt 去掉重复的列名.txt 取n到m条记录.txt 合并字符串.txt 多列的行转列.sql 多行补充.sql 多表对多表进行统计.txt 大小写转换.txt 子查寻和内联查寻.txt 学生名次.txt ...

    Oracle数据库SQL语句优化总结

    一、操作符优化  1、IN 操作符  用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。...  推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。  

    数据库操作语句大全(sql)

    10、说明:几个简单的基本的sql语句 选择:select * from table1 where 范围 插入:insert into table1(field1,field2) values(value1,value2) 删除:delete from table1 where 范围 更新:update table1 set field1...

    MySQL数据库:表的创建SQL语句.pptx

    表的创建-SQL语句 课程目标 掌握 —— 显示数据表文件和表结构的语法格式。 掌握 —— 创建数据表的语法格式; 表的创建 show tables; 说明:用于显示已经建立的数据库表文件 显示数据库表语法格式 表的创建 创建...

    MySQL数据库:数据库的创建SQL语句.pptx

    create database [if not exists] 数据库名 [[default] character set 字符集名] [[default] collate 校对规则名] 说明: []为可选项 其他关键词不区分大小写 显示字符集语法: show charset; ;MySQL命令行登录和...

    图书管理系统数据库设计及sql语句.docx

    字段名 数据类型 能否为空 注释 UserId int 用户id主键,自增 ,读者编号 OpenId int 识别用户 UserName Char(20) 姓名, LastTime Datetime 上次登陆时间 UserPhone Int 电话 图书管理系统数据库设计及sql语句全文共...

    数据库实验报告 SQL查询 ,子查询组合

    实验目的和要求:,了解SQL语句的数据定义与数据更新功能,了解SQL语句的查询功能,掌握SQL中的数据定义语句的用法,熟练掌握SQL中的插入、修改和删除语句的操作,熟练掌握使用SQL语句进行数据库的简单查询、连接...

    用于生成数据字典的SQL语句

    /*SQL Server数据库字典(查询所有的表结构)*/ SELECT TOP 100 PERCENT --a.id, CASE WHEN a.colorder = 1 THEN d.name ELSE '' END AS 表名, CASE WHEN a.colorder = 1 THEN isnull(f.value, '') ELSE '' END AS ...

    2020尚硅谷 谷粒商城 建表sql语句

    drop table if exists pms_attr; drop table if exists pms_attr_attrgroup_relation; drop table if exists pms_attr_group; drop table if exists pms_brand; drop table if exists pms_category; drop table...

    MySQL数据库:数据库的管理SQL语句.pptx

    数据库和表的创建和管理;...drop database [if exists] 数据库名 说明: []是可选项,代表“如果存在”则删除,对应于创建中的“如果不存在”;exit 或者 quit 或者 \q;数据库打开、修改和删除 MySQL退出的方式;谢谢

    数据库精选sql语句练习题 sql语句练习题

    解法二:select tname,depart from teacher a where not exists (select * from course b where a.tno=b.tno); 解法三:SELECT TNAME,DEPART FROM TEACHER WHERE TNO NOT IN (SELECT TNO FROM COURSE); NOT IN的方法...

    经典SQL语句大全

    10、说明:几个简单的基本的sql语句 选择:select * from table1 where 范围 插入:insert into table1(field1,field2) values(value1,value2) 删除:delete from table1 where 范围 更新:update table1 set field1...

    hive sql语句查询

    数据库相关操作 Hive配置单元包含一个名为 default 默认的数据库. create database [if not exists] ;---创建数据库 show databases; --显示所有数据库 drop database if exists &lt;database name&gt; ...

    SQL数据库常用语句练习

    if exists (select * from sys.databases where name = ’数据库名’) drop database [数据库名] if exists (select * from sys.objects where id = object_id(N’[表名]’) ) drop table [表名] create ...

    Oracle数据库、SQL

    三、 SQL语句的处理过程 7 3.1 SQL语句处理过程 7 3.2处理一条select语句 7 四、 where子句 8 4.1 where子句后面可以跟什么 8 4.2语法和执行顺序 8 4.3字符串是大小写敏感的,在比较时严格区分大小写 8 4.4 where...

    SQL中EXISTS与IN

    详细介绍了sql语句中的EXISTS与IN的区别,对于这方面有点模糊的可以参考这篇文档

    SQL语句整理

    //创建数据库 if not exists意为如不存在 use db_name;//使用或者打开 数据库 show databases;//查看所有数据库 alter database db_name;//修改数据库 drop database if exists db_name;//删除数据库 if exists意为...

    数据库SQL实战题目汇总

    数据库SQL实战题目汇总 43.将所有to_date为9999-01-01的全部更新为 NULL.md44.将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005.md 45.将titles_test表名修改为 titles_2017.md 46.在audit表上创建外键...

    oracle数据库sql的优化总结

    五:select语句中尽量避免使用*(执行时会把*依次转换为列名); 六:尽量多的使用commit; 七:Decode可以避免重复扫描相同的记录或重复连接相同的表; 八:通过内部函数也可提高sql效率; 九:连接多个表时,使用...

Global site tag (gtag.js) - Google Analytics