SQL进阶教程——EXISTS谓词的用法(第八章)

mac2024-12-17  15

1. 前言

支撑SQL和关系数据库的基础理论主要有两个:一个是数学领域的集合论;另一个是作为现代逻辑学标准体系的谓词逻辑。本节将重点介绍EXISTS谓词,EXISTS不仅可以将多行数据作为整体来表达高级的条件,而是使用关联子查询时性能任然非常好,这对SQL来说是不可或缺的功能。 SQL采用的是狭义的“一阶谓词逻辑”,这是因为SQL里的EXISTS谓词最高只能接受一阶的实体作为参数。

2. 理论篇

什么是谓词 实际上,谓词是一种特殊的函数,返回值是真值。返回值是true,false,unknown 在关系型数据库里,表中的一行数据可以看做是一个命题

谓词分类 一介谓词:输入值为一行的谓词(=,between) 二阶谓词:输入值为行的集合(exists) 三阶谓词:输入值为集合的集合 …

关系数据库中实体的阶层

0阶:行 1阶:表(行的集合) 2阶:表的集合

全程量化和存在量化 全称量词:所有的x都满足条件p 存在量词:至少存在一个满足条件p的x exists谓词实现了谓词逻辑中的存在量词,不过全称量词和存在量词可以互相转换

德.摩根定律 所有的X都满足条件P=不存在不满足条件P的X 存在X满足条件P=并非所有的X都不满足条件P

3. 查询表中“不”存在的数据

Meeting 第1次第1次伊藤第1次水岛第1次坂东第2次伊藤第2次宫田第3次坂东第3次水岛第3次宫田 -- 求出缺席者的SQL语句(1):存在量化的应用 SELECT DISTINCT m1.meeting,m2.person FROM Meetings AS m1 CROSS JOIN Meetings AS m2 WHERE NOT EXISTS (SELECT * FROM Meetings AS m3 WHERE m1.meeting = m3.meeting AND m2.person = m3.person); -- 求出缺席者的SQL语句(2):使用差集运算 SELECT m1.meeting,m2.person FROM Meetings AS m1,Meetings AS m2 EXCEPT SELECT meeting,person FROM Meetings;

4. 全程量化:习惯“肯定<-——>”之间的转换

student_idsubjectscore100数学100100语文80100理化80200数学80200语文95300数学40300语文90400社会55400数学80 -- 查出所有科目分数都在50分以上的学生 SELECT DISTINCT student_id FROM TestScores AS TS1 WHERE NOT EXISTS (SELECT * FROM TestScores AS TS2 WHERE TS2.student_id = TS1.student_id AND TS2.score < 50) -- 仅就本题而言,还可以使用min(score)>=50

5. 集合VS谓词——哪个更强大

EXISTS和HAVING有一个地方很像,即都是以集合而不是个体为单位来操作数据。实际上,两者在很多情况都是可以互换的,用其中一个写出的查询语句,大多时候都可以用另一个来写。

Projects projectstep_nbrstatusAA1000完成AA1001等待AA1002等待B2000等待B2001等待CS3000完成CS3001完成CS3002等待CS3003等待DY4000完成DY4001完成DY4002完成 --查询完成了工程1的项目:面向集合的解法 SELECT project_id FROM Projects GROUP BY project_id HAVING COUNT(*) = SUM(CASE WHEN step_nbr <= 1 AND status = '完成' THEN 1 WHEN step_nbr > 1 AND status = '等待' THEN 1 ELSE 0 END); --查询完成了工程1的项目:谓词逻辑的解法 SELECT * FROM Projects P1 WHERE NOT EXISTS (SELECT status FROM Projects P2 WHERE P1.project_id = P2.project_id --以项目为单位进行条件判断 AND status <>CASE WHEN step_id <= 1 --使用双重否定来表达全程量化命题 THEN '完成' ELSE '等待' END);

与HAVING相比

缺点 代码看起来不是那么好理解优点 性能好,只要有一行满足,查询就会终止,不一定需要查询所有行的数据。而且还能通过连接条件使用project_id"列的索引。结果里能包含的信息量更大。如果使用HAVING,结果会被聚合,我们只能获取到项目ID,而如果使用EXISTS,则能把集合里的元素整体都获取到

6. 对列进行量化:查询全是1的行

keycol1col2col3col4col5col6col7col8col9col10AB3C1111111111D9E3199

说这张表设计不好的原因是,数组中的元素可以自由地增加或者减少,而表中的列却不能。即使只是增加或者减少一列,都非常麻烦。 相反,行的增加或者减少却对系统几乎没有影响。因此在设计表时有一条原则:让列具有一定的扩展性。数组中的元素不应该对应表中的列,而是应该对应行

--“列方向”的全程量化:不优雅的解答 SELECT * FROM ArrayTbl WHERE col1=1 AND col2=1 . . . col3=1; --"列方向"的全程量化:优雅的解答 SELECT * FROM ArrayTbl WHERE 1=ALL(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10); --"列方向"的存在量化(1) SELECT * FROM ArrayTbl WHERE 9=ANY(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10); --"列方向"的存在量化(2) SELECT * FROM ArrayTbl WHERE 9 IN (col1,col2,col3,col4,col5,col6,col7,col8,col9,col10);

本节要点:

SQL中的谓词指的是返回真值的函数EXISTS与其他谓词不同,接受的参数是集合因此EXISTS可以看成一种高阶函数SQL中没有与全称量词相当的谓词,可以使用NOT EXISTS代替
最新回复(0)