1. 集合成员资格:
eg: 找出选修了ID为10101的教师所教授的课程段的学生数
select count(distinct id)
from takes
where (course_id, sec_id, semester, year)
in (select course_id,sec_id, semester, year
from teaches
where teach.id=10101);
remarks:
- 集合跟集合里面的属性会一一对应
- null跟null会被视为不匹配
2. 集合的比较:
eg: 找出工资至少比biology系某一个教师工资要高的所有教师姓名——用”
select name
from instructor
where salary > some (select salary
from instructor
where dept_name='biology');
remarks:
- =some等价于in
- >some表示“至少比一个大
- any跟some用法一样
eg:找出平均工资最高的系
select dept_name
from instructor
group by dept_name
having avg(salary) >= all (select avg(salary)
from instructor
group by dept_name);
- 类似的, >all是“比所有的都大”
3. 空关系测试
- exist在where的子查询中作为参数使用,非空返回true
- not exists (B except A) 等价于关系A包含关系B,用于测试子查询结果集中是否不存在元组
4. 重复元组存在测试
eg: 找出所有在2009年最多开设一次的课程
select T.course_id
from course as T
where unique (select R.course_id
from section as R
where T.course_id=R.course_id and R.year=2009);
--等价于
select T.course_id
from course as T
where 1>= (select count(R.course_id)
from section as R
where T.course_id=R.course_id and R.year=2009);
remarks:
- 如果作为参数的子查询结果里面没有重复的元组,unique 将返回true
- 可以用not exist 测试在一个子查询的结果中是否存在重复元素
5. from子句中的子查询
eg: 找出所有系中工资总额最大的系
select max(tot_salary)
from (select dept_name, sum(salary)
from instructor
group by dept_name) as dept_total(dept_name, tot_salary);
remarks:
- 哪里用子查询的逻辑是:任何select-from-where表达式返回的结果都是关系,因而可以被插入到select-from-where中任何关系可以出现的位置
- 如果想在from嵌套的子查询里面用来自from其他关系的属性,有的DB里面支持lateral可以实现
6. with子句
eg: 查出所有工资总额大于所有系平均工资总额的系
with dept_total(dept_name, value) as
(select dept_name, sum(salary)
from instructor
group by dept_name),
dept_total_avg(value) as
(select avg(value)
from dept_total)
select dept_name
from dept_name, dept_total_avg
where dept_total.value>=dept_total_avg.value;
remarks:
- with子句提供临时定义关系的方法,只对包含该子句的查询有效
- 优点是逻辑更清晰,还允许在一个查询内多个地方使用视图定义
7. 标量子查询
- 当子查询只返回包含单个属性的单个元组时(即只有一行一列),SQL允许其出现在任何单个表达式能出现的地方,比如select中