当前位置:   article > 正文

Oracle exists与not exists的用法总结_oracle exists用法

oracle exists用法

一、简介

exists(subquery):  如果子查询查询的结果不为空,说明子查询有值,返回真,则执行主查询sql;如果子查询查询的结果为空,说明子查询没值,返回假,则不会执行主查询sql。 
not exists(subquery):  not exists和exists相反,子查询语句结果为空,则表示where条件成立,执行sql语句,否则不执行。

注意:子查询中使用 NULL 仍然返回结果集
select * from TableIn where exists(select null)
等同于: select * from TableIn

下面,以一个示例说明exists与not exists的用法,以及与in、not in的比较。

二、用法详解

【a】首先,我们先创建两个表: department部门表与employee员工表,建表语句如下:

  1. -- Create table
  2. create table DEPARTMENT
  3. (
  4. depid VARCHAR2(128) not null,
  5. depname VARCHAR2(128)
  6. )
  7. tablespace TEST_TABLESPACE
  8. pctfree 10
  9. initrans 1
  10. maxtrans 255
  11. storage
  12. (
  13. initial 64K
  14. next 1M
  15. minextents 1
  16. maxextents unlimited
  17. );
  18. -- Add comments to the table
  19. comment on table DEPARTMENT
  20. is '部门表';
  21. -- Add comments to the columns
  22. comment on column DEPARTMENT.depid
  23. is '部门ID';
  24. comment on column DEPARTMENT.depname
  25. is '部门名称';
  26. -- Create/Recreate primary, unique and foreign key constraints
  27. alter table DEPARTMENT
  28. add constraint DEP_PK_ID primary key (DEPID)
  29. using index
  30. tablespace TEST_TABLESPACE
  31. pctfree 10
  32. initrans 2
  33. maxtrans 255
  34. storage
  35. (
  36. initial 64K
  37. next 1M
  38. minextents 1
  39. maxextents unlimited
  40. );
  41. -- Create table
  42. create table EMPLOYEE
  43. (
  44. empid VARCHAR2(128) not null,
  45. empname VARCHAR2(128),
  46. empsalary NUMBER,
  47. depid VARCHAR2(128)
  48. )
  49. tablespace TEST_TABLESPACE
  50. pctfree 10
  51. initrans 1
  52. maxtrans 255
  53. storage
  54. (
  55. initial 64K
  56. next 1M
  57. minextents 1
  58. maxextents unlimited
  59. );
  60. -- Add comments to the table
  61. comment on table EMPLOYEE
  62. is '员工表';
  63. -- Add comments to the columns
  64. comment on column EMPLOYEE.empid
  65. is '员工ID';
  66. comment on column EMPLOYEE.empname
  67. is '员工名称';
  68. comment on column EMPLOYEE.empsalary
  69. is '员工工资';
  70. comment on column EMPLOYEE.depid
  71. is '所属部门主键ID';
  72. -- Create/Recreate primary, unique and foreign key constraints
  73. alter table EMPLOYEE
  74. add constraint PK_ID primary key (EMPID)
  75. using index
  76. tablespace TEST_TABLESPACE
  77. pctfree 10
  78. initrans 2
  79. maxtrans 255
  80. storage
  81. (
  82. initial 64K
  83. next 1M
  84. minextents 1
  85. maxextents unlimited
  86. );
  87. alter table EMPLOYEE
  88. add constraint FK_DEP_ID foreign key (DEPID)
  89. references DEPARTMENT (DEPID);

表创建完成后,我们插入一些测试数据:

  1. insert into department (DEPID, DEPNAME)
  2. values ('001', '研发部');
  3. insert into department (DEPID, DEPNAME)
  4. values ('002', '人力资源部');
  5. insert into department (DEPID, DEPNAME)
  6. values ('003', '测试部');
  7. insert into department (DEPID, DEPNAME)
  8. values ('004', '市场部');
  9. insert into employee (EMPID, EMPNAME, EMPSALARY, DEPID)
  10. values ('01', '张三', 1000, '001');
  11. insert into employee (EMPID, EMPNAME, EMPSALARY, DEPID)
  12. values ('02', '李四', 2000, '002');
  13. insert into employee (EMPID, EMPNAME, EMPSALARY, DEPID)
  14. values ('03', '王五', 3000, '003');
  15. insert into employee (EMPID, EMPNAME, EMPSALARY, DEPID)
  16. values ('04', '赵六', 4000, '001');
  17. insert into employee (EMPID, EMPNAME, EMPSALARY, DEPID)
  18. values ('05', '田七', 5000, '002');
  19. commit;

【b】案例一:查询存在员工的部门信息

  1. --查询存在员工的部门信息
  2. select dep.depid, dep.depname
  3. from department dep
  4. where exists (select * from employee emp where emp.depid = dep.depid)

如图,我们过滤掉了市场部这个部门没有员工的数据。

以上sql使用in也可以达到相同的效果:

  1. --查询存在员工的部门信息
  2. select d.depid, d.depname
  3. from department d
  4. where d.depid in (select e.depid from employee e)

【c】案例二:查询部门平均工资不小于3000元的部门信息(未过滤没有员工的部门信息)

首先我们先查询每个部门的平均工资:

  1. --查询每个部门的平均工资
  2. select avg(empsalary) avgsal, e.depid, d.depname
  3. from employee e
  4. left join department d
  5. on d.depid = e.depid
  6. group by e.depid, d.depname;

需要查询平均工资不少于3000的,可以使用not exists来实现:

  1. --查询部门平均工资不小于3000元的部门信息(未过滤没有员工的部门信息)
  2. select *
  3. from department de
  4. where not exists (select em.depid
  5. from employee em
  6. where em.depid = de.depid
  7. group by em.depid
  8. having(avg(em.empsalary) < 3000))

可以看到,市场部这个部门并没有员工,但是查询结果也查询出来了。

not exists可以使用not in来达到同样的效果:

  1. --相当于使用in:
  2. select depa.depid, depa.depname
  3. from department depa
  4. where depa.depid not in
  5. (select empl.depid
  6. from employee empl
  7. group by empl.depid
  8. having(avg(empl.empsalary) < 3000))

如果需要过滤掉没有员工的部门,可以进行一下改造。

【d】案例三:查询部门平均工资不小于3000元的部门信息(过滤掉没有员工的部门信息)

  1. -- 查询部门平均工资不小于3000元的部门信息(过滤掉没有员工的部门信息)
  2. select *
  3. from department de
  4. where not exists (select em.depid
  5. from employee em
  6. where em.depid = de.depid
  7. group by em.depid
  8. having(avg(em.empsalary) < 3000))
  9. and exists
  10. (select * from employee empl where empl.depid = de.depid)

在没有过滤没有员工的基础上加上exists(select * from employee empl where empl.depid = de.depid)就可以过滤了。

同样我们也可以用not in来实现:

  1. --相当于使用in:
  2. select depa.depid, depa.depname
  3. from department depa
  4. where depa.depid not in
  5. (select empl.depid
  6. from employee empl
  7. group by empl.depid
  8. having(avg(empl.empsalary) < 3000))
  9. and depa.depid in (select emplo.depid from employee emplo)

三、exists与in效率比较

  1. --语句一:使用exists实现
  2. select dep.depid, dep.depname
  3. from department dep
  4. where exists (select * from employee emp where emp.depid = dep.depid)
  5. --语句二:使用in实现
  6. select d.depid, d.depname
  7. from department d
  8. where d.depid in (select e.depid from employee e)

以上两个语句,语句二使用in的效率没有语句一使用exists的效率高。

原因分析:

【a】oracle在执行exists语句,执行的时候会先检查主查询语句,然后运行子查询知道找到匹配的第一项。

【b】oracle在执行in语句的时候,首先执行子查询,并将获取的结果存在一个有索引的临时表中,在执行子查询之前,主查询出于挂起状态,直到子查询执行完毕,存放在临时表中以后主查询才会执行,而且in查询不走索引。

【c】基于上面两点,exists是对主查询循环,所以exists适合主查询那张表数据量比较小,子查询对应表数据量大的场景;in是先执行子查询,所以in适合子查询数据量小、主查询对应表数据量大的场景。

四、总结

实际工作中,需要根据具体的需求来决定是使用exists还是in语句,本文是笔者对exists和in语句使用的一些总结,仅供大家学习参考,共同学习,共同进步!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/479956
推荐阅读
相关标签
  

闽ICP备14008679号