详细聊聊sql中exists和not exists用法

目录
  • exists:
  • exists 和in 的区别
  • not exists详细介绍:
  • 附案例分析
  • 总结

之所以要说这个问题,是因为项目中用到了not exists,但两者写的语句只有一点差别,结果一个有问题了,一个没问题。具体问题下面详细说明,先来看看exists如何应用。

exists:

强调的是是否有返回集,不需知道具体返回的是什么,比如:

      SELECT
	*
      FROM
	customer
     WHERE
	 not EXISTS (
		SELECT
			0
		FROM
			customer_goods
		WHERE
			customer_id = 1
	)

只要exists引导的子句有结果集返回,这个条件就算成立。这个返回的字段始终是0,改成1,则始终返回的是1,所以exists不

在乎返回的是什么内容,只在乎是否有结果集返回。

exists 和in 的区别

这二者最大的区别,是使用in只能返回一个字段值

     SELECT
	*
     FROM
	customer c
     WHERE
     c.id
	 not in (
		SELECT
			customer_id
		FROM
			customer_goods
		WHERE
			customer_id = 1
	)

但exists允许返回多个字段。

not in 和not exists 分别为in 和exists的对立面。

exists(sql 返回结果集为真)

not exists(sql 不返回结果集为真)

not exists详细介绍:

表customer:

表customer_goods:

二者的干系:customer_goods.customer_id = customer.id

(1) 查询:

     SELECT
	*
     FROM
	customer c
     WHERE
	NOT EXISTS (
		SELECT
			*
		FROM
			customer_goods	cg
                WHERE
                        cg.customer_id =1
	)

结果:

无返回结果

(2)查询:

    SELECT
	*
    FROM
	customer c
    WHERE
	NOT EXISTS (
		SELECT
			*
		FROM
			customer_goods	cg
                WHERE
                         c.id =1
	)

结果:

(3)分析:

发现二者差别只是是否not exists字句查询的查询条件是否跟外面查询条件有关,如果not exists子查询只有自己本身的查询条件,这样只要子查询中有数据返回,就证明是false,结果在整体执行就无返回值;一旦跟外面的查询关联上,就能准确查出数据。

而我遇到的问题正是这个。

经过分析,我认为一旦跟外层查询关联上,就会扫描外面查询的表。而没一旦二者不添加关联关系,只会根据not exists返回是否有结果集来判断,这也是为什么一旦子查询有数据,就查不到所有的数据了。

附案例分析

来看看not exists或exists是如何用的吧。

# 学生表
CREATE TABLE `Student`(
    `s_id` VARCHAR(20),
    `s_name` VARCHAR(20) NOT NULL DEFAULT '',
    `s_birth` VARCHAR(20) NOT NULL DEFAULT '',
    `s_sex` VARCHAR(10) NOT NULL DEFAULT '',
    PRIMARY KEY(`s_id`)
);
# 课程表
CREATE TABLE `Course`(
    `c_id`  VARCHAR(20),
    `c_name` VARCHAR(20) NOT NULL DEFAULT '',
    `t_id` VARCHAR(20) NOT NULL,
    PRIMARY KEY(`c_id`)
);
# 教师表
CREATE TABLE `Teacher`(
    `t_id` VARCHAR(20),
    `t_name` VARCHAR(20) NOT NULL DEFAULT '',
    PRIMARY KEY(`t_id`)
);
# 成绩表
CREATE TABLE `Score`(
    `s_id` VARCHAR(20),
    `c_id`  VARCHAR(20),
    `s_score` INT(3),
    PRIMARY KEY(`s_id`,`c_id`)
);
# 插入学生表测试数据
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('08' , '王菊' , '1990-01-20' , '女');
#课程表测试数据
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
# 教师表测试数据
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
#成绩表测试数据
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

题目是查询和"01"号的同学学习的课程完全相同的其他同学的信息,直接做确实有点麻烦,我们可以先做做这题:查看学了所有课程的同学的信息。

学了所有课程的同学的信息,那不就是这些同学没有一门课程没有学吗。

select * from Student st where not exists(select * from Course c
where not exists(select * from Score sc where sc.c_id = c.c_id
and sc.s_id = st.s_id));

然后我们再回过来看这题,把所有的课程换成01同学学的课程。

select * from Student st where not exists(select * from
( select s2.c_id as c_id from Student s1
inner join Score s2 on s1.s_id = s2.s_id where s1.s_id = 01) t
where  not exists (select * from Score sc
where sc.c_id = t.c_id and sc.s_id = st.s_id and st.s_id != 01));

总结

到此这篇关于sql中exists和not exists用法的文章就介绍到这了,更多相关sql exists和not exists用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • sqlserver exists,not exists的用法

    学生表:create table student( id number(8) primary key, name varchar2(10),deptment number(8))选课表:create table select_course(  ID         NUMBER(8) primary key,  STUDENT_ID NUMBER(8) foreign key (COURSE_ID) references course(ID),  COURSE_ID  NUMBER(8) for

  • mssql和sqlite中关于if not exists 的写法

    在sql语名中,if not exists 即如果不存在,if exists 即如果存在. 下面学习下二者的用法. a,判断数据库不存在时 复制代码 代码如下: if not exists(select * from sys.databases where name = 'database_name') b,判断表不存在时 复制代码 代码如下: if not exists (select * from sysobjects where id = object_id('table_name') a

  • sql not in 与not exists使用中的细微差别

    上面两个简单的Sql,我们从表面理解,查询的最终结果应该是一样的,但实际结果却和我们想象的不一样 第一条sql查询的结果有一条数据 第二条sql查询的结果却为空 原因: not exists的子查询,对于子查询不返回行和子查询返回行的查询结果是有区别的 这些细小的差别千万不要被我们所忽视,一旦项目庞大了,想跟踪到具体的错误所花费的时间也是可观的.尽量把这些不必要的错误扼杀在摇篮里. 啰嗦了,呵呵. 上面两个简单的Sql,我们从表面理解,查询的最终结果应该是一样的,但实际结果却和我们想象的不一样

  • sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句

    在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.在子查询中,NOT IN子句将执行一个内部的排序和合并.无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历).为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS. 如 我要查询 Sendorder表中的冗余数据(没有和reg_person或worksite相连的数

  • mysql exists与not exists实例详解

    mysql exists与not exists实例详解 tableA |column1 | column1 |column3 | tableb |column1 | column1 |column3 | 要查询 tableA 的数据,条件是是 tableA.column1 不在 tableB 的 tableB.column2 中 也就是要得到类似以下语句的效果(not in 效果不完全等同于 not exists , 如果子查询中出现空记录, 则整个查询语句不会返回数据) SELECT a.*

  • 详细聊聊sql中exists和not exists用法

    目录 exists: exists 和in 的区别 not exists详细介绍: 附案例分析 总结 之所以要说这个问题,是因为项目中用到了not exists,但两者写的语句只有一点差别,结果一个有问题了,一个没问题.具体问题下面详细说明,先来看看exists如何应用. exists: 强调的是是否有返回集,不需知道具体返回的是什么,比如: SELECT * FROM customer WHERE not EXISTS ( SELECT 0 FROM customer_goods WHERE

  • 数据库SQL中having和where的用法区别

    "Where" 是一个约束声明,使用Where来约束来之数据库的数据,Where是在结果返回之前起作用的,且Where中不能使用聚合函数. "Having"是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在Having中可以使用聚合函数. 聚合函数,SQL基本函数,聚合函数对一组值执行计算,并返回单个值.除了 COUNT 以外,聚合函数都会忽略空值. 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用. Transact-SQL编程

  • 聊聊C#中的Mixin的具体用法

    目录 写在前面 从一个简单例子说起 在类中实现单例 在父类中实现单例 轮到Mixin出场 定义 Mixin在C#中 在8.0之前 从C#8.0开始 写在前面 Mixin本意是指冰淇淋表面加的那些草莓酱,葡萄干等点缀物,它们负责给冰淇淋添加风味.在OOP里面也有Mixin这个概念,和它的本意相似,OOP里面的Mixin意在为类提供一些额外功能——在不破坏类本身或者它的继承链的基础上,在某些情况下可能会起到妙用.今天跟着小编一起来看看吧. 从一个简单例子说起 试想我们在写一个游戏引擎,创建如下类:

  • SQL中limit函数语法与用法(MYSQL获取限制某行数据)

    1.limit函数的语法和用法 (1)常用且简单的语法和用法 ①语法:limit n 即limit <参数> 具体语法:select <字段1>,...,<字段n> from <表名> (where <条件> order by <字段1>...<字段n> asc|desc) limit n 说明:括号内的语句可省略 参数说明: n:为阿拉伯数字,表示前n行. ②用法:用于获取前n行数据. (2)另一种(两个参数)语法和用法

  • 详细聊聊Mybatis中万能的Map

    目录 万能的Map demo map 实现add user map 实现通过id查询 多个参数可以使用Map进行传参 总结 万能的Map 假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们需要考虑使用Map 简单来说,map你用什么参数就写什么参数,而实体类需要写所有参数. map不需要名称完全对应,通过键的映射取值,实体类必须要求和实体类中属性名字一样 map传递参数,直接在sql中取出key即可 [parameterType="map"] 对象传递参数,直接在sql中取对

  • 详细聊聊MySQL中慢SQL优化的方向

    目录 前言 SQL语句优化 记录慢查询SQL 如何修改配置 查看慢查询日志 查看SQL执行计划 如何使用 SQL编写优化 为何要对慢SQL进行治理 总结 前言 影响一个系统的运行速度的原因有很多,是多方面的,甚至可能是偶然性的,或前端,或后端,或数据库,或中间件,或服务器,或网络等等等等,真正的去定位一个问题需要对系统有一定的认知,可以根据自身的判断去缩小问题范围. 今天不说其他的优化,单独把数据库的优化拿出来说几个优化方向. 跟系统的优化方向一样,数据库的优化,同样也是多方面的,其中涵盖着SQ

  • 详细聊聊SpringBoot中动态切换数据源的方法

    其实这个表示有点不太对,应该是 Druid 动态切换数据源的方法,只是应用在了 springboot 框架中,准备代码准备了半天,之前在一次数据库迁移中使用了,发现 Druid 还是很强大的,用来做动态数据源切换很方便. 首先这里的场景跟我原来用的有点点区别,在项目中使用的是通过配置中心控制数据源切换,统一切换,而这里的例子多加了个可以根据接口注解配置 第一部分是最核心的,如何基于 Spring JDBC 和 Druid 来实现数据源切换,是继承了org.springframework.jdbc

  • 详细聊聊MySQL中的LIMIT语句

    目录 问题 server层和存储引擎层 那LIMIT是什么鬼? 怎么办? 吐个槽 最近有多个小伙伴在答疑群里问了小孩子关于LIMIT的一个问题,下边我来大致描述一下这个问题. 问题 为了故事的顺利发展,我们得先有个表: CREATE TABLE t ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, key1 VARCHAR(100), common_field VARCHAR(100), PRIMARY KEY (id), KEY idx_key1 (key1

  • 详细聊聊vue中组件的props属性

    目录 问题一:那props具体是怎么使用呢?原理又是什么呢?往下看 问题二:那如果我们想给年龄加1岁,怎么实现? 问题三:对于年龄这一类型,我们最希望拿到的是什么数据类型? 问题四:可以限制类型,那是不是也可以限制是否必传呢? 问题五:props接收的属性值可以修改吗? 问题六:必须要修改props属性值,怎么办? 总结:配置项props 总结 今天这篇文章,让你彻底学会props属性-- props主要用于组件的传值,他的工作就是为了接收外面传过来的数据,与data.el.ref是一个级别的配

  • 详细聊聊JDK中的反模式接口常量

    目录 前言 常量接口 类接口 枚举类型 结束语 前言 在实际开发过程中,经常会需要定义一个文件,用于存储一些常量,这些常量设计为静态公共常量(使用 public static final 修饰).这个时候就出现两种选择: 在接口中定义常量,比如 JDK 1.1 中的 java.io.ObjectStreamConstans 接口: 在类中定义常量,比如 JDK 1.7 中的 java.nio.charset.StandardCharsets: 这两种方式都能够达到要求:存储常量.无需实例化.下面

随机推荐