SQL嵌套子查询

目录

  • 嵌套子查询
    • 集合成员资格
    • 集合的比较
    • 空关系测试
    • 重复元组存在性测试
    • from子句中的子查询
    • with子句
    • 标量子查询

嵌套子查询

子查询是嵌套在另一个查询的where子句中的select-from-where表达式。通常用于对集合的成员资格、集合的比较以及集合的基数进行检查。

集合成员资格

  • in:测试元组是否是集合中的成员
  • not in:测试元组是否不是集合中的成员

单属性关系中测试成员资格

select distinct course_id
from section
where semester = 'Fall' and year = 2009 and
    course_id in (select distinct course_id
                  from section
                  where semester = 'Spring' and year = 2010);

innot in也能作用于枚举集合

select distinct name
from instructor
where name not in ('Mozart','Einsten');

测试任意关系的成员资格

select count(distinct ID)
from takes
where(course_id,sec_id,semester,year)in(select course_id,sec_id,semester,year
                                        from teaches
                                        where teaches.ID = 10101);

集合的比较

  • > some:至少比某一个要大(anysome的用法大致相同)

找出满足下面条件的所有教师的姓名,他们的工资至少比Biology系某一个教师的工资要高

select name
from instructor
where salary >some (select salary
                    from instructor
                    where dept_name = 'Biology');
  • SQL同时也允许<=some>=some=some<>some的比较,=some等价于in,然而<>some并不等价于not in
  • >all比所有都大
  • SQL同时也允许<=all>=all=all<>all的比较,<>all等价于not in,然而=all并不等价于in

空关系测试

  • exists:测试子查询结果中是否存在元组,在作为参数的子查询非空时返回true
  • not exists:测试子查询结果中是否不存在元组,在作为参数的子查询为空时返回true

子查询通常都用“*”,existis的子查询只返回真值或假值,给出列名并无实际意义

找出在2009年秋季学期和2010年春季学期同时开课的 所有课程

select sname 
from s 
where exists
    (select * 
     from sc
     where sc.sno=s.sno and cno=001);

来自外层查询的相关名称(上述例子中S)可以用在where子句中


找出选修了Biology系开设的所有课程的学生
可以将“关系A包含关系B”写成“not exists (B except A)
对每个学生测试其选修的所有课程集合是否包含Biology系开设的所有课程

select S.ID,S.name
from student as S
where not exists((select course_id
                  from course
                  where dept_name = 'Biology')
                  except
                  select T.course_id
                  from takes as T
                  where S.ID = T.ID);

重复元组存在性测试

  • unique:测试子查询结果是否存在重复元组,如果没有出现重复元组,返回true
  • not unique:测试子查询结果是否存在重复元组,如果出现重复元组,返回true

找出所有在2009年最多开设一次的课程
  如果某课程在2009年开设大于一次,则会出现重复的course_id查询结果,unique就会返回false
  一个元组的多个副本中,只要有一个属性为空,unique就有可能为真,因为元组t1和t2某个域为空时,判断t1=t2为假

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);

from子句中的子查询

  任何select-from-where表达式返回的结果都是关系,因而可以被插入到另一个select-from-where中任何关系可以出现的位置

原先 having子句的查询

select dept_name,avg(salary)
from instructor 
group by dept_name
having avg(salary) > 42000;

写成 from子句的子查询后
  可以用as子句给此子查询的结果关系起个名字,并对属性进行重命名

select dept_name,avg_salary
from (select dept_name,avg(salary) as avg_salary
      from instructor
      group by dept_name)
      as dept_avg(dept_name,avg_salary)
where avg_salary > 42000;
  • lateral:使 from子句访问它前面的表或者子查询中的属性

目前只有少数SQL支持lateral,如果没有lateral子句,子查询就不能访问来自外层查询的相关变量I1。

select name,salary,avg_salary
from instructor I1,lateral(select avg(salary) as avg_salary
                           from instructor I2
                           where I2.dept_name = I1.dept_name);

with子句

with:提供定义临时关系的方法,只对包含with子句的查询有效

找出具有最大预算值的系

with max_budget(value)as
    (select max(budget)
     from department)
select budget
from department,max_budget
where department.budget = max_budget.value;

标量子查询

  SQL允许子查询出现在返回单个值的表达式能够出现的任何地方,只要该子查询只返回包含单个属性的单个元组。

列出所有的系以及他们拥有的教师数

select dept_name
    (select count(*)
     from instructor
     where department.dept_name = instructor.dept_name)
     as num_instructors
from department;

你可能感兴趣的:(SQL,数据库,sql,数据库,database)