SQL进阶-9-EXISTS谓词的使用
支撑SQL和关系数据库的两个重要理论基础:
- 数学领域的集合论
- 现代逻辑学标准体系的谓词逻辑(predicate logic)
本文中重点介绍的是谓词exists
的用法
extists谓词不仅可以将多行数据作为整体来表达高级的条件,还可以在使用关联子查询时表现出良好的性能。
什么是谓词
SQL保留字中有很多的谓词,比如:
- <、>、=等比较谓词
Between、 like、in、is、null
等
谓词就是函数;谓词是一种特殊的函数,返回的真值,结果都是true、false、unknown(一般的谓词逻辑中没有unknown,但是SQL采用的是三值逻辑,因此具有三种值)
exists属于二阶谓词,is、between等属于一阶谓词
谓词逻辑提供谓词是为了判断命题的真假
exists的参数
参数不是单一的某个值:参数是行记录的集合
1 | select id |
Exists的子查询中,select子句的列表中可以有3种写法:
1 | -- 1-通配符 |
全称量化和存在量化
所有的x都满足条件P:全称量词
存在满足条件P的x:存在量词,exists
实现的是存在量词
SQL中没有实现全称量词的函数或者谓词
但是全称量词和存在量词二者之前可以相互转换
- 所有的x都满足条件P:不存在不满足条件P的x
- 存在满足条件P的x:并非所有的x都不满足条件P
SQL中实现全称量化,需要将所有的行都满足条件P
转成不存在不满足条件P的行
案例1-查询没有参会人员
需求
从Meeting
表中找出没有参会的人员
SQL实现
假设所有人都参加了全部的会议,生成了一个集合,再用该集合减去现有的数据即可。生成全部的会议的集合使用交叉联结:
1 | select distinct M1.meeting, M2.person |
使用存在量化求解:
1 | select distinct M1.meeting, M2.person |
使用差集求解:
1 | select distinct M1.meeting, M2.person |
笔记:肯定=双重否定
exists实现全称量化
记住一点:所有的行都满足X等价于不满足X的行一行都不存在
需求1-指定分数以上
学生成绩表score,从中找出每门成绩都在50以上的学生,答案是100、200、400
SQL实现
1 | -- 所有科目都在50分以上 等价于 没有一个科目不满足50分 |
需求2-查询分数
某个学生的所有行记录中,如果科目是数学,则分数在80分以上;如果科目是语文,则分数在50以上
SQL实现
1 | select distinct student_id |
加上条件:如何排除400的同学,因为他只有一门存在分数。使用having条件进行过滤
1 | select (distinct) student_id -- 通过student_id进行了聚合,可以不用distinct |
需求3-查询全是1的行
从下面的表中找出全部是1的行
SQL实现
1 | -- 不推荐 |
如果要查询至少存在一个NULL
的行记录:
coalesce函数表示参数至少存在一个满足条件
1 | select * |
小结
SQL
谓词指的是返回值为真值的函数EXISTS
与其他谓词不同,接受的参数是集合;可以看做是一种高阶函数SQL
中没有实现全称量词相当的谓词,但是可以通过not exists
来代替