MySQL-笔记-06.数据高级查询

news2024/11/26 12:21:15

目录

6.1 连接查询

6.1.1 交叉连接(cross join)

6.1.2 内连接(inner join)

6.1.3 外连接(outer join)

6.1.3.1 左外连接(left [outer] join)

6.1.3.2 右外连接(right [outer] join)

6.1.4 自连接(cross join)

6.2 嵌套查询

6.2.1 单值嵌套查询

6.2.2 多值嵌套查询

6.2.2.1 使用in运算符

6.2.2.2 使用比较运算符的子查询

6.2.2.3 使用any、all运算符

6.2.2.4 使用EXISTS连接的子查询

6.3 集合查询

6.3.1 union形成并集

6.3.2 except形成差集

小结:

6.1 连接查询

        数据库本着精简的设计原则,通常将数据存放于不同的表中,最大限度地减少数据冗余。在实际应用中,经常需要从多个数据表中查询满足一定条件的记录,这时就要用到连接查询。

连接查询分为交叉连接内连接外连接自连接

6.1.1 交叉连接(cross join)

        交叉连接返回被连接表中所有数据行的笛卡尔积

        查询结果集的总行数=被连接表行数的乘积总列数=被连接表列数的总和

        其基本语法格式如下:

SELECT * FROM 表名1 CROSS JOIN 表名2

        在from子句中也可以省略cross join,使用逗号分隔被连接的表,

        其基本语法格式如下:

SELECT * FROM 表名1 , 表名2

         交叉连接产生的结果集一般没有实际应用的意义,所以这种连接很少使用。

6.1.2 内连接(inner join)

        内连接是最常使用的连接查询方式,通过inner join或者join连接两个表,结果集中只包含满足连接条件的记录。连接条件通常采用“主键 = 外键”的形式。

        内连接创建连接关系有以下两种方式:

①在WHERE子句中创建连接关系,两个表名出现在FROM子句中,其基本语法格式如下:

SELECT 列名列表
FROM 表名1 , 表名2 WHERE 表名1.列名 = 表名2.列名

② 在FROM子句中创建连接关系,其基本语法格式如下:

SELECT 列名列表
FROM 表名1 [ INNER ] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.102】查询所有选课学生的学号、所选课程的名称和成绩。

SELECT score.cno, cname, grade
FROM course, score
WHERE course.cno = score.cno;		/*在WHERE子句中给出等值连接查询条件*/

 【例3.103】查询男学生的选课情况。要求列出学号、姓名、性别、课程名、课程号和成绩。

-- 方法1
SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A INNER JOIN score B ON A.sno = B. sno 	/*可省略INNER*/
     INNER JOIN course C ON B.cno = C.cno 
WHERE (A.ssex = '男') ; 


-- 方法2
SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A, score B, course C
WHERE A.sno = B. sno AND B.cno = C.cno AND A.ssex = '男';

6.1.3 外连接(outer join)

        在内连接查询中,结果集只包括满足连接条件的数据行,但有时用户也希望在结果集中能显示那些不满足连接条件的数据,这就需要使用外连接查询

        外连接操作的类型可分为左外连接和右外连接。

        在创建外连接时,表在SQL语句中出现的顺序非常重要。

        出现在JOIN左边的表是“左表”,出现在JOIN右边的表是“右表”。

6.1.3.1 左外连接(left [outer] join)

        左外连接指定在结果集中除了包括由内连接返回的所有行之外,还包括左表中所有不满足连接条件的行,并将结果集中右表的输出列设置为NULL。

        因此,左外连接可以使得左表中的所有记录都显示在结果集中

        左外连接是对连接条件中左边表不加限制,其基本语法格式如下:

SELECT 列名列表 
FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.102】student表左外连接score表。

SELECT A.sno, A.sname, B.cno, B.grade 
FROM student A LEFT OUTER JOIN score B ON A.sno = B.sno;
6.1.3.2 右外连接(right [outer] join)

        右外连接指定结果集中除了包括由内连接返回的所有行之外,还包括右表中所有不满足连接条件的行,并将结果集中左表的输出列设置为NULL。

        因此,右外连接可以使得右表中的所有记录都显示在结果集中

        右外连接是对连接条件中右边表不加限制,其基本语法格式如下:

SELECT 列名列表 
FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.107】teacher表右外连接lesson表。

SELECT A.tno, A.tname, B.*
FROM teacher A RIGHT OUTER JOIN lesson B ON A.tno = B.tno;

6.1.4 自连接(cross join)

        自连接是指一个表自己与自己建立连接,也称为自身连接

        若要在一个表中找具有相同列值的行,则可以使用自连接。

        使用自连接时需要为表指定两个别名,且对所有列的引用均要用别名限定

【例3.101】查询选修“数据库原理”(课程号01301)课程的成绩高于学号为202301020101的学生的成绩的所有学生信息,并按成绩从高到低排列。

SELECT x.* 
FROM score x , score y			/*将成绩表score分别取别名为x和y*/
WHERE x.cno= '01301' and x.grade > y. grade and 
	y.sno= '202301020101' and y.cno= '01301' 
ORDER BY x. grade DESC;

 多学一招:

        在连接查询时,若数据表连接的字段同名,则连接时的匹配条件可以使用using代替on

        基本语法格式如下:

SELECT 列名列表
FROM 表名1 [ inner | left | right ] join 表名2 
using(列名)

 【例3.103】查询男学生的选课情况。要求列出学号、姓名、性别、课程名、课程号和成绩。

SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A JOIN score B USING(sno)
              INNER JOIN course C USING(cno) 
WHERE (A.ssex = '男') ; 

 注意:

        如果连接的表中有相同的列名,要求加上表名或表别名作为前缀来限定列名,即用“表名.列名”或“表别名.列名”表示,明确列名来自哪个数据表,否则系统将无法执行此查询,并提示错误信息。表别名往往是一个缩短了的表名,如果定义了表别名,则不能使用表名。如果列名不重名,可以不加表名或表别名前缀。

        连接查询,需要根据要解决的问题进行分析

  •         结果来自哪几个表(确定连接表)?
  •         表之间建立怎样的连接(确定连接类型)?
  •         选取怎样的数据(SELECT 字段名)?

只有将这些问题搞清楚,才可能写出正确的语句。

6.2 嵌套查询

        在SQL语言中,一个SELECT … FROM … WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块中的查询称为嵌套查询。

在嵌套查询中,上层查询块称为外层查询或父查询,下层查询块称为内层查询或子查询。        

SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其他子查询。

嵌套查询一般按照由里向外的顺序处理,即先处理最内层的子查询,然后一层一层向外处理,直到最外层查询块。

需要注意以下几点:

  • 子查询语句必须用圆括号括起来
  • 子查询中不能使用ORDER BY子句,ORDER BY子句只能对最终查询结果进行排序。
  • 有些嵌套查询可以用连接查询替代

6.2.1 单值嵌套查询

 单值嵌套查询是指子查询返回一个单一的值(即标量)。

【例3.109】查询选修“数据库原理”课程的所有学生的学号和成绩。

-- 方法1
SELECT sno, grade 
FROM score 
WHERE cno=( 
   SELECT cno 
   FROM course 
   WHERE cname='数据库原理');

-- 方法2
ELECT S.sno, S.grade 
FROM score S JOIN course C  USING(cno)
WHERE  cname='数据库原理';

6.2.2 多值嵌套查询

        多值嵌套查询是指子查询返回一个结果集,这个结果集包含多行数据

        这种子查询通常与any、all、in、not in、exits、not exits等操作符一起使用。

6.2.2.1 使用in运算符

        IN 是属于的意思,等价于“=ANY”,即等于子查询结果集中的任何一个值。

【例3.110】查询与“陈嘉宁”在同一个班级学习的学生。

-- 方法1
SELECT sno, sname, clsno
FROM student
WHERE clsno IN  -- in可以换成=
    (SELECT clsno 
     FROM student
     WHERE sname= '陈嘉宁')
-- 方法2
SELECT S1.sno, S1.sname, S1. clsno
FROM student S1 JOIN student S2 USING(clsno)
WHERE S2.sname = '陈嘉宁'

 【例3.111】查询选修了课程名为“数据结构”课程的学生的学号和姓名。

-- 方法1
SELECT sno, sname
FROM student
WHERE sno IN (
	SELECT sno
	FROM score
	WHERE cno IN (
		SELECT cno
		FROM course
		WHERE cname= '数据结构'
	)
)

-- 方法2
SELECT student.sno, sname
FROM student, score, course
WHERE student.sno = score.sno AND score.cno = course.cno AND course.cname= '数据结构' 
6.2.2.2 使用比较运算符的子查询

        带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。

        当用户确切知道内层查询返回单个值时,可以用>、<、=、>=、<=、!=或<>等比较运算符。

【例3.112】查询与“陈嘉宁”在同一个班级学习的学生。

SELECT sno, sname, clsno
FROM student
WHERE clsno =
    (SELECT clsno 
     FROM student
     WHERE sname= '陈嘉宁')

 【例3.113】找出每个学生超过他选修课程平均成绩的课程号。

SELECT cno
FROM score x
WHERE grade >= (
    SELECT AVG (grade) 
    FROM score y
    WHERE y.sno=x.sno)
6.2.2.3 使用any、all运算符

        子查询返回单值可以用比较运算符,但返回多值时要用ANY(SOME)或ALL谓词修饰符。

        而使用ANY或ALL谓词的时候必须同时使用比较运算符。 其基本语法格式如下:

expression {> | >= | = | < | <= | <> | != | <=> } { ALL | ANY | SOME } ( subquery )

      

 【例3.114】查询其他班级中比“2023计科1班”某一学生年龄小的学生的姓名和出生日期。

        1.首先找出“2023计科1班”中所有学生的年龄,构成一个集合

        2.找所有不是“2023计科1班”且年龄小于上述集合中任一值的学生

SELECT sname, sbirthday 
FROM student
WHERE sbirthday  < ANY ( SELECT sbirthday
                         FROM student
                         WHERE clsno  =( SELECT clsno                                                
                                         FROM class
                                         WHERE clsname= '2023计科1班')
                        ) 
                   AND clsno<> ( SELECT clsno
                                 FROM class
                                 WHERE clsname= '2023计科1班' 
                                ) 

 ANY和ALL谓词有时可以用集函数实现

ANY与ALL与集函数的对应关系

        用集函数实现子查询通常比直接用ANY或ALL查询效率要高

        因为前者通常能够减少比较次数

 练习: 找出比女生年龄都小的学生的学号、姓名和性别。

-- 方法1
select sno,sname, ssex
from student
where sbirthday > all (
	select sbirthday    
	from student  
	where ssex ='女' )

-- 方法2
select sno,sname, ssex
from student
where sbirthday > (
	select max(sbirthday)   
	from student  
	where ssex ='女' )
6.2.2.4 使用EXISTS连接的子查询

        EXISTS和NOT EXISTS关键字用来确定数据是否在子查询结果集中存在。

exists表示子查询至少返回一行时条件成立,

not exists表示子查询中没有任何记录返回时条件成立

        使用exists连接子查询时,相当于对外部查询的数据行进行了一次存在测试。

        外部查询的where子句测试满足子查询的行是否存在。

        带有exists的子查询不返回任何数据行,它只返回true或false。

【例3.118】查询教师工号为“01001”的教师讲授的课程的课程号、课程名和学时。

SELECT cno, cname, chour
FROM course
WHERE EXISTS (
   SELECT * FROM lesson WHERE cno=course.cno AND tno='01001');


SELECT cno, cname, chour
FROM course
WHERE cno IN (
   SELECT cno FROM lesson WHERE tno='01001');


SELECT cno, cname, chour
FROM course
WHERE '01001' IN (
   SELECT tno FROM lesson WHERE cno=course.cno);


SELECT DISTINCT course.cno, cname, chour
FROM course INNER JOIN lesson USING(cno) WHERE tno='01001';

 【例3.119】查询还没有学生选课的课程信息。

SELECT * FROM course A 
WHERE NOT EXISTS
(SELECT cno FROM score WHERE cno=A.cno);

【练习】 查询没有选修01101号课程的学生学号、姓名。

SELECT sno, sname
FROM student
WHERE NOT EXISTS(SELECT *
                 FROM score
                 WHERE score.sno = student.sno  AND cno='01101');

 【练习】查询选修全部课程的学生姓名。

-- 方法1
SELECT sname
FROM student
WHERE NOT EXISTS (SELECT *  FROM course
              	  WHERE NOT EXISTS (SELECT * FROM score
                   		            WHERE sno= student.sno
                      	            AND cno= course.cno
		                            )
                  );
-- 方法2
select sname
From student
Where sno IN(select sno
             from score
             Group by sno
             Having count(*) = (select count(*) from course)
             )

6.3 集合查询

        集合运算符将来自两个或多个查询的结果合并到单个结果集中。T-SQL支持三种集合运算:并集(UNION)、交集(INTERSECT)、差集(EXCEPT)。

集合运算的限定条件如下:

(1)子结果集要具有相同的结构。

(2)子结果集的列数必须相同。

(3)子结果集对应的数据类型必须可以兼容。

(4)每个子结果集不能包含ORDER BY和COMPUTE子句。

集合运算的语法如下:

select_statement
集合运算符
select_statement
[集合运算符] select_statement … ]

6.3.1 union形成并集

【例3.120】查询“2023计科1班”的学生或2005年以后出生的学生。

SELECT *
FROM student
WHERE clsno= '2023010101'
UNION
SELECT *
FROM student
WHERE YEAR (sbirthday) > 2005;

SELECT DISTINCT *
FROM student
WHERE clsno= '2023010101' OR YEAR (sbirthday) > 2005;

6.3.2 except形成差集

【例3.122】查询“2023计科1班”的学生与2005年以后出生的学生的差集。

SELECT *
FROM student
WHERE clsno= '2023010101'
EXCEPT
SELECT *
FROM student
WHERE YEAR (sbirthday) > 2005;

SELECT DISTINCT *
FROM student
WHERE clsno= '2023010101' AND YEAR (sbirthday) <= 2005;

小结:

实施查询任务,可按照以下步骤进行分析,并逐步实现。

步骤1:分析查询涉及的表,包括查询条件和查询结果涉及的表,确定是单表查询,还是多表查询,确定FROM子句中的表名。

步骤2:如果是多表查询,分析确定表与表之间的连接条件,即确定FROM子句中ON后面的连接条件

步骤3:分析查询是针对所有行,还是选择部分行。如果是选择部分行,使用WHERE子句,确定WHERE子句中的行条件表达式。

步骤4:分析查询是否要进行分组统计计算。如果需要分组统计,则使用GROUP BY子句,确定分组的列名。然后分析分组后是否要对组进行筛选,如果需要,则使用HAVING子句,确定组筛选条件。

步骤5:确定查询目标列表达式,即确定查询结果包含的列名或列表达式,确定SELECT子句后的目标列表达式。

步骤6:分析是否要对查询结果进行排序,如果需要排序,则使用ORDER BY子句,确定排序的列名和排序方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1604368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Meta因露骨AI图片陷入困境

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Postgresql源码(126)TupleStore使用场景与原理分析

相关 《Postgresql源码&#xff08;125&#xff09;游标恢复执行的原理分析》 《Postgresql游标使用介绍&#xff08;cursor&#xff09;》 总结 开源PG中使用tuple store来缓存tuple集&#xff0c;默认使用work_mem空间存放&#xff0c;超过可以落盘。在PL的returns setof场景…

回文链表leecode

回文链表 偶数情况奇数情况 回文链表leecode 偶数情况 public boolean isPalindrome(ListNode head) {if (head null) {return true;}ListNode fast head;ListNode slow head;while (fast ! null && fast.next ! null) {fast fast.next.next;slow slow.next;}//反…

Day43:LeedCode 1049. 最后一块石头的重量 II 494. 目标和 474.一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果…

Excel文件解析(Java)

一、概述 在应用程序的开发过程中&#xff0c;经常需要使用 Excel文件来进行数据的导入或导出。所以&#xff0c;在通过Java语言实现此类需求的时候&#xff0c;往往会面临着Excel文件的解析(导入&#xff09;或生成&#xff08;导出)。 在Java技术生态圈中&#xff0c…

Java实现RSA加密示例代码

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 RSA加密是一种非对…

如何配置Postgres的自动扩展功能以应对数据增长

文章目录 解决方案1. 表空间管理2. 分区表3. 自动扩展配置4. 监控和告警5. 使用外部工具和服务 示例代码示例1&#xff1a;创建表空间示例2&#xff1a;创建分区表示例3&#xff1a;调整配置参数示例4&#xff1a;使用监控和告警工具 总结 在PostgreSQL中&#xff0c;随着数据的…

QT-编译报库错误(LF/CRLF)

QT-安装后环境问题记录 版本和环境问题 版本和环境 QT5.15.2 Windows10 QT Creator 问题 在QT夸端开发的项目中 &#xff0c;使用QTCreator打开项目pro文件&#xff0c;编译报出很多系统库 及本地文件中的一些问题&#xff0c;具体如图&#xff1a; 后续&#xff0c;我以为…

宠物店小程序如何搭建制作?宠物店小程序核心功能有哪些?

随着宠物经济的兴起&#xff0c;宠物店的线上服务需求日益增长。微信小程序作为一种便捷的线上服务平台&#xff0c;为宠物店提供了一个与爱宠人士建立联系的新渠道。面对市场上众多的小程序开发选项&#xff0c;宠物店应该如何选择或制作一款适合自己的小程序呢&#xff1f;本…

Java高阶私房菜:快速学会异步编程CompletableFuture

为了使主程代码不受阻塞之苦&#xff0c;一般使用异步编程&#xff0c;而异步编程架构在JDK1.5便已有了雏形&#xff0c;主要通过Future和Callable实现&#xff0c;但其操作方法十分繁琐&#xff0c;想要异步获取结果,通常要以轮询的方式去获取结果&#xff0c;具体如下&#x…

登录github突然出现Two-factor authentication怎么办?

起因 今天想登录github下载项目&#xff0c;输入用户名密码认证之后竟然弹出来了Two-factor authentication&#xff0c;像下图&#xff0c;我只记得之前好像开启过这玩意&#xff0c;但是不知道哪里找这个code了。 解决 在你的iphone里面搜索密码。然后找到github网页&…

程序员能做什么副业?增收致富就靠它们了

作为一个程序员&#xff0c;大家都习惯了朝九晚六&#xff0c;时不时加班的生活。虽然工资听起来比其他行业高一些&#xff0c;但是&#xff0c;都是靠命拼出来的。如何摆脱这种枯燥乏味且前途未卜的生活&#xff0c;应该是很多程序员都在考虑的事情。 而作为一个做了十几年的…

【微服务-Ribbon】什么是负载均衡?微服务中负载均衡有哪些策略呢?

前面几篇文章&#xff0c;我们了解了一下Nacos的单机部署、集群部署以及微服务接入Nacos的步骤。从本篇开始&#xff0c;我们来看一下微服务第二个通用组件-负载均衡&#xff08;Ribbon&#xff09;。 1、Ribbon负载均衡器 负载均衡顾名思义&#xff0c;是指通过软件或者硬件…

javaWeb智能医疗管理系统

简介 在当今快节奏的生活中&#xff0c;智能医疗系统的崛起为医疗行业带来了一场革命性的变革。基于JavaWeb技术开发的智能医疗管理系统&#xff0c;不仅为医疗机构提供了高效、精准的管理工具&#xff0c;也为患者提供了更便捷、更个性化的医疗服务。本文将介绍一个基于SSM&a…

LInux shell编程之基础语法

目录 1、shell概述 1.1、查看Linux 提供的 Shell 解析器 1.2、bash 和 sh 的关系 1.3、查看系统&#xff08;centos&#xff09;默认使用的解释器 2、脚本的基础使用 2.1、脚本的格式 2.2、脚本的执行方式 方式一&#xff1a;采用 bash / sh 脚本的相对路径或绝对路径…

【LeetCode刷题记录】160. 相交链表

160 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函…

沂水六景记 ——齐源堂主王志强撰文

沂水六景记 ——齐源堂主王志强 明清时期&#xff0c;非常流行“八景”。所谓“八景”&#xff0c;就是在本地众多的风景名胜之中&#xff0c;选定八个最有代表性的美景&#xff0c;分别取上悦耳动听的名字&#xff0c;然后分别题诗。这种给风景选美的做法&#xff0c;是文人…

ASP.NET基于TCP协议的简单即时通信软件的设计与实现

摘 要 即时通信(Instant Message)&#xff0c;由于其具有实时性、跨平台性、成本低、效率高等优点而受到广泛的使用。设计并实现一个能够处理多用户进行实时、安全的即时通信系统具有较强的现实意义。即时通信的底层通信是通过SOCKET套接字接口实现的。当前的主流UNIX系统和微…

2W,3KVDC隔离 定电压输入,稳压单、双路输出DC-DC模块电源——TPI-2W 系列

TPI-2W系列产品是专门针对PCB上需要与输入电源隔离的电源应用场合而设计的。该产品适用于&#xff1a;1&#xff09;输入电源的电压变化≤5%&#xff1b;2&#xff09;输入输出之间要求隔离电压≥3000VDC&#xff1b;3&#xff09;对输出电压稳定和输出纹波噪声要求高.

linux 安装openjdk-1.8

安装命令 yum install java-1.8.0-openjdk-1.8.0.262.b10-1.el7.x86_64查看安装路径 find / -name java 默认的安装路径 /usr/lib/jvm 查看到jre 以及java-1.8.0-openjdk-1.8.0.262.b10-1.el7.x86_64 配置环境变量 vim /etc/profile 添加的内容 export JAVA_HOME/usr/li…