Sql学习笔记4——嵌套子查询(上)

嵌套子查询

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

1、集合成员资格

SQL允许测试元组在关系中的成员资格。连接词in测试元组是否是集合中的成员,集合是由select子句产生的一组值构成的。连接词not in测试元组是否不是集合中的成员。

考虑“找出在2009年秋季和2010年春季学期同时开课的所有课程。”按之前所学知识,可以通过对两个集合进行并运算来书写该查询。如下:

  (select course_id

  from section

  where semester=‘Fall’ and year=2009)

  intersect

 (select course_id

  from section

  where semester=‘Spring’ and year=2010);

现在考虑,先找出在2009年秋季开课的所有课程,再看它们是否也是2010年春季开课的课程集合中的成员。很明显,这个查询与前者结果一样。

  (select distinct course_id  /*此查询不会自动去重复,因此必须要用distinct*/

  from section

  where semester=‘Fall’ and year=2009)and

     course_id in(select course_id

          from section

          where semester=‘Spring’ and year=2010);

in 与not in也可以用于枚举集合。如,下列查询找出既不叫A也不叫B的教师的姓名:

  select distinct name

  from instructor

  where name not in(‘A‘,‘B‘);

2、集合的比较

考虑查询“找出满足下面条件的所有老师的姓名,他们的工资至少比Biology系某一个教师的工资要高。”在之前,我们写法如下:

  select distinct T.name

  from instructor as T,instructor as S  /*更名运算常用场合*/

  where T.salary>S.salary and S.dept_name=‘biology‘;

在SQL中,短语“至少比某一个要大”在SQL中用>some表示,此结构允许我们用一种更加贴近字面表述的查询:

  select name

  from instructor

  where salary>some(select salary

             from instructor

             where dept_name=‘Biology‘);

此外,SQL也允许<some, <=some, >=some,=some和<>some的比较。易知=some等价于in,然而<>some并不等价于not in。

稍微改一下上述查询的条件,考虑“找出满足下面条件的所有老师的姓名,他们的工资至少比Biology系每个教师的工资要高。”

结构>all对应词组”比所有的都大“。写法如下:

  select name

  from instructor

  where salary> all(select salary

             from instructor

             where dept_name=‘Biology‘);

类似地,SQL也允许<all,<=all,>=all,=all和<>all的比较。易知<>all 等价于not in 但=all不等价于in

3、空关系测试:exists与 not exists(*难点)

SQL还有一个特性是可测试一个子查询的结果中是否存在元组。exists结构在作为参数的子查询非空时返回true。

使用exists结构,写出查询“找出2009年秋季学期和2010年春季学期同时开课的所有课程。”

  select course_id

  from section as S

  where semester = ‘Fall‘  and year=2009 and

    exists(select *

       from section as T

       where semester=‘Spring‘ and year = 2010 and

       S.course_id=T.course_id);

上述查询说明了SQL的一个特性,来自外层的查询的一个相关名称(上述查询中的S)可以用在where子句的子查询中。这种使用了来自外层相关名称的子查询称为相关子查询。

注:只要有exists都是相关子查询,exists返回的只是一个bool值,测试子查询结果中是否有元组。

not exists 结构用于测试子查询结果中是否不存在元组。可以用not exists来模拟集合包含操作:

例如,关系A包含关系B可以写成”not exists(B except A)“

考虑查询”找出选修了biology系开设所有课程的学生“。我们可以理解为:某些学生选修的课程包含了biology系所开设的所有课程。使用not exists-except结构如下:

  select S.id,S.name

  from student as S

  where not exists((select course_id

           from course

            where dept_name=‘biology’)  /*子查询1,找出biology系开设的所有课程的集合*/

           except

          (select S.id

          from takes as T

          where S.id=T.id));    /*子查询2,找出S.id选修的所有课程*/

本例中,外层select对每个学生测试其所选修的所有课程集合是否包含biology系所开设的所有课程集合。

4)重复元组存在性测试

SQL提供一个布尔函数,用于测试在一个子查询的结果中是否存在重复元组。如果作为参数的子查询结果中没有重复的元组,unique结构将返回true。(此结构并未被广泛实现,sql server2012都不支持)

考虑查询”找出所有在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);

若不使用unique,如下:

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

我们可以用not unique结构测试在一个子查询中是否存在重复元组。

考虑查询“找出所有在2009年最少开设两次的课程”

  select T.course_id

  from course as T

  where not unique(select R.course.id

          from section as R

          where T.course_id=R.course_id and R.year = 2009);

  

时间: 2024-11-06 14:39:58

Sql学习笔记4——嵌套子查询(上)的相关文章

Sql学习笔记4——嵌套子查询(下)

5)from子句中的子查询 因为SQL任何select-from-where表达式返回的都是关系,所以from子句中允许使用子查询表达式. 考虑查询“找出平均工资超过42000美元的那些系中教师的平均工资”,之前我们用having子句来书写该查询. 现在我们不用having子句,如下: select dept_name,avg_salary from(select dept_name,avg(salary) as avg_salary from instructor group by dept_

SQL学习之学会使用子查询

1.SELECT语句是SQL的查询.我之前的随笔中所用的SELECT语句都是简单的查询,即从单个数据库表中检索数据的单条SELECT语句. 查询:任何SQL语句都是查询,但此术语一般指SELECT语句. 2.SQL不仅允许简单的SELECT查询,还允许创建子查询,即嵌套在其他查询中的查询. 下面通过实例来了解子查询在实际项目中的应用: create database Study gouse Study go create table Customers( Id int identity(1,1)

《MySQL必知必会学习笔记》:子查询

子查询 在开始了解子查询之前,首先做下准备工作,建立3个表, 一个是customers表,其中包括:客户名字.客户ID.客户Tel等. 一个是orders表,其中包括:订单号.客户ID.订单时间等. 一个是ordersitems表,其中包括:订单物品.订单号.物品数量. 准备工作 1.建表 建customers表的命令如下,其它的表与之类似: create table customers(cust_name varchar(10),cust_id int(10),cust_tel varchar

SQL学习笔记_04_多表查询

一.概念: 1.多表连接有以下几种分法: (1)内连接           vs          外连接 (左.右.满) (2)等值连接        vs         不等值连接 (3)非自连接        vs         自连接 2.笛卡尔集:  所有表中的所有行互相连接 产生条件:(1)多表查询没有连接条件 (2)连接条件无效 3. 内连接   :  结果集中不包含一个表与另一个表不匹配的行 外连接   :  两个表在连接过程中除了返回满足连接条件的行以外(这里的数据是内连接

SQL嵌套子查询和相关子查询的执行过程有什么区别(推荐)

SQLServer子查询可以分为 相关子查询 和 嵌套子查询 两类.前提, 假设Books表如下: 类编号 图书名 出版社 价格 -------------------------------------------------------- 2 c#高级应用 圣通出版 23.00 2 Jsp开发应用 机械出版社 45.00 3 高等数学 济南出版社 25.00 3 疯狂英语 清华大学出版社 32.00 嵌套子查询的执行不依赖与外部的查询. 执行过程: (1)执行子查询,其结果不被显示,而是传递

Oracle之PL/SQL学习笔记

自己在学习Oracle是做的笔记及实验代码记录,内容挺全的,也挺详细,发篇博文分享给需要的朋友,共有1w多字的学习笔记吧.是以前做的,一直在压箱底,今天拿出来整理了一下,给大家分享,有不足之处还望大家批评指正. PL/SQL定义:PL/SQL是由Oracle开发,专门用于Oracle的程序设计语言. PL---Procedural Language. SQL—Structure QueryLanguage.PL/SQL包括过程化语句和SQL语句     PL/SQL的单位:块. 一个块中可以嵌套

Oracle之PL/SQL学习笔记之触发器

Oracle之PL/SQL学习笔记之触发器 触发器是许多关系数据库系统都提供的一项技术.在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块. 触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行. 即触发器是当某个事件发生时自动地隐式运行.并且,触发器不能接收参数.所以运行触发器就叫触发或点火(firing).ORACLE事件指的是对数据库的表进行的INSERT. UPDATE及D

SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比

原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写,希望高手们不要见笑.下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了. 从这里下载文件employ

IBatis.Net学习笔记六--再谈查询

在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的方式.在上一篇文章中我提到了三种方式,都是各有利弊:第一种方式当数据关联很多的情况下,实体类会很复杂:第二种方式比较灵活,但是不太符合OO的思想(不过,可以适当使用):第三种方式最主要的问题就是性能不太理想,配置比较麻烦. 下面是第四种多表查询的方式,相对第二种多了一点配置,但是其他方面都很好(当然