第5讲 MySql数据操纵语句--复杂查询

5.1 连接查询

交叉连接

定义

  • 当一条查询涉及到多个表时,称为连接查询。主要的连接查询包括:
    • 等值连接查询和非等值连接查询
    • 自然连接查询
    • 自身连接查询
    • 多表查询
    • 外连接查询

等值与非等值连接查询

  • 等值和非等值连接查询实际是先在两个关系之间实现交叉连接(广义笛卡尔积),再选择满足条件的元组组成新关系。

例:查询学生的选修课程的情况

自然连接查询

  • 是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是相同的属性组,并且在结果中把重复的属性列去掉,称为自然连接。
  • 例:用自然连接的方式查询学生的选修课程的情况
    • SELECT
    • FROM Students S NATURAL JOIN Reports R;
  • 注:
    • 自动将两个表中所有相同的属性列进行等值比较
    • 运行结果中去掉所有重复的属性列

例:用自然连接的方式查询每个学生的选修课程的情况

自然连接查询

  • 思考1:执行下列语句,系统是否会提示出错?

SELECT Sno, Sname, Cno, Grade

FROM Students S NATURAL JOIN Reports R;

  • 思考2:如果是将包含了完全相同的属性列名的两个表建立自然连接,会得到什么样的返回结果?

例:A(id, name),B(id, name)

SELECT * FROM A NATURAL JOIN B;

自身连接查询

  • 进行连接查询的是同一个表中的数据
  • 其基本方法是在SELECT语句的FROM子句中给用来连接的两个相同表名的表取两个不同的别名。
  • 例:查询课程的间接先修课
  • SELECT A.Cno, A.Cname, A.Pre_Cno, B.Pre_Cno
  • FROM Courses A, Courses B
  • WHERE A.Pre Cno = B.Cno;

例:查询课程的间接选修课

多表连接查询

  • 两个以上的表连接完成的查询
  • 例:查询学生的学号、姓名、选修的课程名及成绩
  • 使用USING完成连接
  • 例:查询学生的学号、姓名、选修的课程名及成绩
  • 注意
    • USING只能和JOIN一起使用
    • 要求两个关联字段在关联表中名称一致。
    • 只能表示关联字段值相等
  • 注意
    • 要控制连接表的数量。多表连接就相当于嵌套for循环一样,非常消耗资源,会让SQL查询性能下降得很严重,因此不要连接不必要的表。在许多DBMS中,也都会有最大连接表的限制。
    • 需要JOIN的字段,数据类型要保持绝对一致;多表关联查询时,保证被关联的字段需要有索引

外连接查询

  • 选定连接操作中涉及的某个表A为基准,即使另一个表B中没有与之匹配的记录,其结果表中也要求包括表A的所有元组。若表B中没有与之匹配的记录,结果表中涉及表B的属性列全部取空值。
  • 外连接分为:左连接(LEFTJOIN)和右连接(RIGTHJOIN)

例:查询每个学生的基本情况和选课情况

例:查询每门课程都有哪些学生选修及其成绩,结果显课程编号、课程名、学号、成绩、学生姓名

例题

5.2 嵌套查询

  • 将一个查询块(SELECT-FROM-WHERE)嵌套在另一个查询块的WHERE子句或HAVING短语条件中的查询。
  • 基本格式
    • 子查询的结果可以是单个数据值,元组的属性值,或一个新的关系表。

常用的嵌套查询

(1)带谓词IN的嵌套查询

(2)带有比较运算符的嵌套查询

(3)带谓词ANY或ALL的嵌套查询

(4)带谓词EXISTS的嵌套查询

带谓词IN的嵌套查询

带有比较运算符的嵌套查询

  • 当用户能确切知道内层查询返回的是单值时,可以用>,<,=,>=,<=,!=或<>等比较运算符
  • 例:查找高于平均年龄的学生信息

带谓词ANY或ALL的嵌套查询

  • 必须与比较运算符同时使用。ANY表示某个,ALL表示所有

  • 例:查询非计算机与信息工程学院的不超过该学院所有学生的年龄的学生姓名(Sname)和出生日期(Sbirth)

带谓词EXISTS的嵌套查询

  • 不返回任何数据,只产生逻辑值真(True)或假(False)

  • 例:查询选修了编号为'112p0063'课程的学生姓名(Snamie)和所在院号(Dno)

  • 这类查询称为相关子查询

  • 处理过程:

    • 取外层父查询表中的第1个元组
    • 根据它与内层子查询相关的属性值处理内层子查询
    • 若WHERE子句返回值为True,则取此元组放入结果表
    • 再取父查询表的下一个元组
    • 重复上述过程,直至外层父查询表的元组全部检查完为止
  • 例:查询与"许辉"在同一个学院的学生学号(Sno)、姓名(Sname)和所在院号(Dno)

相关子查询

带子关系的嵌套查询

  • 连接的数据表是一个查询得到的新的关系

  • 例:查询大一时学习不积极的学生情况(选课少于2门,包括没有选修过课程的),查询结果显示学生学号(Sno)、姓名(Sname)和选修课程数

  • 提示:先将所有学生大一时的选修情况统计出来,再对结果进行条件筛选,没有选修过课程的学生在选课表中没有记录,所以需要与学生表建立左连接。

  • 例:查询选修了'计算机网络'课程的学生学号姓名和成绩

5.3 集合查询

  • 标准SQL提供了并操作运算命令UNION,将多个SELECT语句的结果进行传统的集合并操作(系统会自动去掉重复的元组)。
  • 这个操作要求参加UNION操作的各个结果表的列数必须相同且对应属性的数据类型也相同。
  • 标准SQL中没有直接提供集合的交和差的操作,但可用其它条件查询来实现
  • 例:查询选修了课程112p0055或选修了课程112p0015的学生的学号
  • 例:查询选修了课程112p0055并且选修了课程112p0015的学生的学号
  • 例:查询选修了课程112p0055但是没有选修了课程112p0015的学生的学号
  • 例:查询计算机与信息工程学院的学生或年龄不大于20岁的学生信息
相关推荐
Wonderful U10 小时前
Python+Django实战:打造智能生鲜果蔬进销存管理系统(采购入库、库存预警、销售开单、毛利统计)
数据库·python·django
Demon1_Coder10 小时前
Day4-微服务-Seata默认事务
java·数据库·微服务
疯狂热爱代码的00后10 小时前
入门必看! MySQL增删改查全套示例SQL 直接复制运行
mysql
我是大猴子10 小时前
Redis为什么不适合做持久化和DB的区别在哪里
数据库·redis·缓存
huipeng92610 小时前
企业级微服务开发实战(二):微服务基础设施搭建与中间件部署
java·redis·mysql·spring cloud·微服务·nacos·rabbitmq
mN9B2uk1710 小时前
数据库锁总结
数据库·oracle
闪电悠米10 小时前
黑马点评-秒杀优化-04_lua_and_db_fallback
服务器·开发语言·网络·数据库·缓存·junit·lua
可乐ea10 小时前
【知识获取与分享社区项目 | 项目日记第 24 天】终章总结:从认证、发布、计数、Feed、搜索到 RAG:完整复盘一个知识社区后端系统
java·spring boot·redis·mysql·elasticsearch·ai·kafka
Jun62610 小时前
QT(5)-第三方日志系统
开发语言·数据库·qt
骄马之死11 小时前
Redis 核心知识点总结
数据库·redis·缓存