SQL谓词指的是返回真值的函数
EXISTS与其他谓词不同,接受的参数是集合
因此EXISTS可以看出一种高阶的函数
SQL中没有与全称量词相当的谓词,可以使用not exists代替
1、存在量化
-- 建表
create table meetings(
meeting varchar(10),
person varchar(10)
);
insert into meetings values ('第一次', '伊藤');
insert into meetings values ('第一次', '水岛');
insert into meetings values ('第一次', '坂东');
insert into meetings values ('第二次', '伊藤');
insert into meetings values ('第二次', '宫田');
insert into meetings values ('第三次', '坂东');
insert into meetings values ('第三次', '水岛');
insert into meetings values ('第三次', '宫田');
求缺席者
-- 存在量化的应用
select DISTINCT m1.meeting, m2.person
from meetings m1 cross join meetings m2
where not EXISTS
(select *
from meetings m3
where m1.meeting = m3.meeting
and m2.person = m3.person)
;
-- 使用差集运算
select m1.meeting , m2.person
from meetings m1,meetings m2
minus
select meeting, person
from meetings
;
结果(oracle)
MEETING PERSON
---------- ----------
第二次 水岛
第二次 坂东
第三次 伊藤
第一次 宫田
2、全称量化
用双重否定
-- 创表
create table testscores(
student_id INTEGER,
subject1 varchar(10),
score INTEGER
);
insert into testscores values(100, '数学', 100);
insert into testscores values(100, '语文', 80);
insert into testscores values(100, '理化', 80);
insert into testscores values(200, '数学', 80);
insert into testscores values(200, '语文', 95);
insert into testscores values(300, '数学', 40);
insert into testscores values(300, '语文', 90);
insert into testscores values(300, '社会', 55);
insert into testscores values(400, '数学', 80);
数学分数在80分以上及语文分数在50分以上的学生
select distinct a.student_id
from testscores a
where a.subject1 in ('数学', '语文')
and not EXISTS
(select *
from testscores b
where b.student_id = a.student_id
and 1 = case when b.subject1 = '数学' and b.score < 80 then 1
when b.subject1 = '语文' and b.score < 50 then 1
else 0 end )
group by a.student_id
having count(*) >= 2
;
结果(oracle)
STUDENT_ID
----------
100
200
3、集合和谓词比较
-- 创表
drop table projects_1_8;
create table projects_1_8(
project_id varchar(10),
step_nbr INTEGER,
status1 varchar(10)
)
;
insert into projects_1_8 values('AA100', 0, '完成');
insert into projects_1_8 values('AA100', 1, '等待');
insert into projects_1_8 values('AA100', 2, '等待');
insert into projects_1_8 values('B200', 0, '等待');
insert into projects_1_8 values('B200', 1, '等待');
insert into projects_1_8 values('CS300', 0, '完成');
insert into projects_1_8 values('CS300', 1, '完成');
insert into projects_1_8 values('CS300', 2, '等待');
insert into projects_1_8 values('CS300', 3, '等待');
insert into projects_1_8 values('DY400', 0, '完成');
insert into projects_1_8 values('DY400', 1, '完成');
insert into projects_1_8 values('DY400', 2, '完成');
查询完成到了工程1的项目
面向集合的解法
select project_id
from projects_1_8
group by project_id
having count(*) = sum(case when step_nbr <= 1 and status1 = '完成' then 1
when step_nbr >= 2 and status1 = '等待' then 1
else 0 end)
;
面向集合的解法——结果(oracle)
PROJECT_ID
----------
CS300
谓语逻辑的解法
-- 谓语逻辑的解法 (双重否定)
select *
from projects_1_8 A
where not EXISTS
(select status1
from projects_1_8 b
where a.project_id = b.project_id -- 以项目为单位进行条件判断
and status1 <> case when step_nbr <= 1 then '完成'
else '等待' end)
;
谓语逻辑的解法——结果(oracle)
PROJECT_ID STEP_NBR STATUS1
---------- ---------- ----------
CS300 3 等待
CS300 2 等待
CS300 1 完成
CS300 0 完成
4、集合和谓词的优缺点
谓词的优点:
1、性能好,只要有一行满足条件就停止,不一定需要查询所有行的数据
2、结果中包含的信息量大。如果用having 会被聚合谓词的缺点:
1、使用了双重否定不容易被理解
>
内容多来自 《SQL进阶教材》,仅做笔记。