支撑SQL和关系数据库的基础理论主要有两个:一个是数学领域的集合论;另一个是作为现代逻辑学标准体系的谓词逻辑。本节将重点介绍EXISTS谓词,EXISTS不仅可以将多行数据作为整体来表达高级的条件,而是使用关联子查询时性能任然非常好,这对SQL来说是不可或缺的功能。 SQL采用的是狭义的“一阶谓词逻辑”,这是因为SQL里的EXISTS谓词最高只能接受一阶的实体作为参数。
什么是谓词 实际上,谓词是一种特殊的函数,返回值是真值。返回值是true,false,unknown 在关系型数据库里,表中的一行数据可以看做是一个命题
谓词分类 一介谓词:输入值为一行的谓词(=,between) 二阶谓词:输入值为行的集合(exists) 三阶谓词:输入值为集合的集合 …
关系数据库中实体的阶层
0阶:行 1阶:表(行的集合) 2阶:表的集合
全程量化和存在量化 全称量词:所有的x都满足条件p 存在量词:至少存在一个满足条件p的x exists谓词实现了谓词逻辑中的存在量词,不过全称量词和存在量词可以互相转换
德.摩根定律 所有的X都满足条件P=不存在不满足条件P的X 存在X满足条件P=并非所有的X都不满足条件P
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,则能把集合里的元素整体都获取到说这张表设计不好的原因是,数组中的元素可以自由地增加或者减少,而表中的列却不能。即使只是增加或者减少一列,都非常麻烦。 相反,行的增加或者减少却对系统几乎没有影响。因此在设计表时有一条原则:让列具有一定的扩展性。数组中的元素不应该对应表中的列,而是应该对应行
--“列方向”的全程量化:不优雅的解答 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代替