MYSQL_深入理解自连接_图书借阅情况(2/2)

光说不练假把式。这就开门见山——引出我们的自连接实例:图书借阅情况。

题目:

 这是一道笔试题目:如果限时5min内完成,同学们可以测试一下自己对于SQL语句的熟练程度。

题目分析:

可以看见这个数据库有三个实体(可称为表):Book,Reader,Borrower。

第一题:

注重考察模糊查询。(关于模糊查询的集中讲解我们放在了:初写MySQL四张表:(4/4)_mysql数据模板-CSDN博客)

第二题: 出题人还是很善良的,不藏着掖着——怕我们纠结选择查询方式,索性两种方式都使用。(这可是我们现学现卖的重点)

第三题:

看见:“借阅人数”,这题十有八九就是考聚合函数和一个排序关键字。

查询书名(BN)以“计”开头的图书信息。

 分析:

‘图书信息’,(这Book单词您得认识),正是Book表里面所含记录。可得我们查询得到的结果集正是来源于Book,它要我们显示‘图书信息’,眼下之意就是包含图书的所有属性。

可得:

SELECT *
FROM Book

它要求查询出来的图书有个条件: 这时候需要我们设置过滤条件,WHERE子句走起

以‘计’为开头的书名(BN),意味着这本书可以就叫《计》,或者“计......”,要实现匹配计后面0个或无数个字符,我们使用通配符%。

模糊查询:关键字LIKE(或者NOT LIKE)搭配 通配符。

WHERE BN LIKE '计%';

所以本题最终代码:

SELECT *
FROM Book
WHERE BN LIKE '计%';

查询比《大学计算机基础》库存量高的图书号(BNo)和书名(BN)(请用子查询和自身连接两种方式)。 

子查询:

我们最后在结果集里面,选中的字段是BNo和BN,来源于Book,可写出以下代码:

SELECT BNo,BN
FROM Book

现在就来考虑考虑过滤条件:比某本书的库存量高的书。

子查询的核心,就是找出谁是被先查询的。反推的话,我们要的结果集是——比某本书的库存量高的中的书们;不难推测,子查询先查的就是——“比某本书的库存量高的书​”中的某本书的库存量​​​​​​

正着理解谁是需要先被查询的,现在未知量有两组:《大学计算机基础》的库存量(Number)和比这个Number大的书们。

很明显在Book表里,我们知道了一本书的书名,很容易就在那一条记录(行)中对照着就找着这本书的库存量了。而知道了这本书的库存量,集中那一列(Number)一一比较,就才能知道哪些库存量较大、较小,然后选出较大库存量的记录,选中目的字段再最后返回结果集。

可知,先知道《大学计算机基础》的库存量(Number),问题才能按逻辑进行。

那么过滤条件:

WHERE Number > (《大学计算机基础》的库存量(Number));

括号里面的查询语句,先执行,这就是子查询。子查询的查询结果作为父查询的查询条件(过滤条件)。

WHERE Number > (SELECT NumberFROM BookWHERE BN = '大学计算机基础');
#过滤条件:只保留书名是“大学计算机基础”的记录,最后在结果集里面选择Number值并返回

所以第二题(子查询)代码:

SELECT BNo,BN
FROM Book
WHERE Number > (SELECT NumberFROM BookWHERE BN = '大学计算机基础');

自连接:

自连接,就是表和自己做连接操作,包括:内连接、外连接和笛卡尔积集连接。实现连接操作通过取别名,代表同一个表不同的实例。

这里总结一个一般规律:JOIN...ON...关键字(内外连接)通常用于表示两个表之间的等价关系(即连接条件)。就正如我们上一小节所谈到的,一张表同时有员工的id号以及他/她的经理的id,同时经理本身也算是公司的员工。这时候在查询每个员工及其经理名字的时候,需要进行表自连接操作,这时候的连接条件是e1.manager_id = e2.employee_id。

这种连接条件,而非比较操作,我们使用JOIN...ON...。说人话,就是匹配条件是等号用JOIN...ON..,其他比较符号可以使用笛卡尔积集查询。

比如此处:

我们不妨令b1、b2分别为Book的别名。我们打算从b1中得到最后的结果集。那b2做什么用?

SELECT b1.BNo,b1.BN
FROM Book b1,Book b2
WHERE 

我们注意看题干,查询比《大学计算机基础》库存量高的图书号(BNo)和书名(BN),现在结果集体现在b1中,但是《大学计算机基础》的库存量在代码中还没有呈现。

可以得到,要构成题意的过滤条件,我们的逻辑还是需要先明确“《大学计算机基础》库存量”再做查询。子查询中,我们使用同一张表,将这个逻辑分了先后。

在自连接查询中,我们选择将这两个任务分配给了两张表,(一张表的两个实例):一个查《大学计算机基础》的库存量,另一张表查询比《大学计算机基础》库存量高的图书号(BNo)和书名(BN)

子查询注重厘清逻辑先后,而自连接查询需要分工明确。

WHERE b1.Number > b2.Number AND b2.BN = '大学计算机基础';

 前者是b1要做的,选中该表库存量(Number)大于b2.Number这个值的记录,b2.Number这个值也不是b2表里随便哪个值,而是书名为《大学计算机基础》的Number。

故第二题(自连接)代码:

SELECT b1.BNo,b1.BN
FROM Book b1,Book b2
WHERE b1.Number > b2.Number AND b2.BN = '大学计算机基础';

查询所有图书的借阅情况,包括书号(BNo)和借阅人数,并且按照借阅人数降序排列。

我们对照题目给出的三张表进行分析:

需求:查询所有图书的借阅情况,包括书号(BNo)和借阅人数,并且按照借阅人数降序排列。 

这最好下手的前两句,SELECT ... FROM ... ,我们看一遍题目就知道。

 要求显示书号BNo和'借阅人数',在Book表和Borrower表里,都有BNo字段,那问题来了:到底BNo的前缀是Book还是Borrower呢?

再细细看题:显示“所有图书”的借阅情况。如果要说哪张表记录的书最完整,那必属Book表。

SELECT Book.BNo, 借阅人数
FROM Book

还有一个字段—— 借阅人数,三张表都没有一个字段直接表示“借阅人数”。出错题了?不是,此时我们应该把目光放在最接近真相的表上,借阅表(Borrower)

 借阅表,展示了读者和图书的借阅关系。在借阅表中,读者体现在“RNo”(读者编号)上;图书体现在“BNo”(书号)上。由于:书名和人名都会有重名的情况,而书号和读者编号不一样,具有唯一标识性,故用这二者作为读者和图书,可构成一张数据不错误、不冗余的借阅表。

要获得每本图书的借阅人数,我们采用聚合函数。这里选用的聚合函数是COUNT();

将每一本书作为一个组,组内数出有多少个读者id号,这样得到的就是每本图书的借阅人数。故COUNT()里面的参数应该为Borrower.RNo。

SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
#题上要求显示的字段名,叫“借阅人数”,需要取别名
FROM 

 分析到这里,我们发现这两个字段都来自不同的表,这不免就会涉及到连接操作。到底是什么连接呢?外连接,内连接亦或者笛卡尔积集连接。

再看一眼题:显示“所有图书”的借阅情况,意味着就算在借阅表里面没有这本书的记录,也应该显示。

一个“所有图书”,就暗示我们谁是主表,主表这个概念存在于外连接中。

那么,代码继续写:

SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
FROM Book
LEFT JOIN Borrower
ON 

观察Book表和Borrower表是否含有相同字段构成连接条件。这种用等价关系匹配的连接,也呼应上前文说的使用JOIN...ON...连接 。

 那么连接条件就是关键的BNo。

SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
FROM Book
LEFT JOIN Borrower
ON Book.BNo = Borrower.BNo

此时查询语句就匹配好了,形成了一个外连接结果集,但是“借阅人数”这个聚合函数还没完成。前面分析提到:

将每一本书作为一个组,组内数出有多少个读者id号,这样得到的就是每本图书的借阅人数。

分组的关键字“GROUP BY”,用Book.BNo代表一本书。

SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
FROM Book
LEFT JOIN Borrower
ON Book.BNo = Borrower.BNo
GROUP BY Book.BNo

GROUP BY子句后面的参数成为分组依据,好理解。注意:参数应包含SELECT语句中的非聚合列。(比如此处的Book.BNo)

SELECT语句中,除了聚合函数计算的列外,其他所有列都应该出现在GROUP BY子句中。否则,查询可能会返回错误,因为非聚合列的值在组内不是唯一的。 

最后一步:“并且按照借阅人数降序排列。”

ORDER BY SCOUNT(Borrower.RNo) DESC;

所以,第三题代码:

SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
FROM Book
LEFT JOIN Borrower
ON Book.BNo = Borrower.BNo
GROUP BY Book.BNo
ORDER BY COUNT(Borrower.RNo) DESC;

三道题的参考代码如下:

SELECT *
FROM Book
WHERE BN LIKE '计%';
SELECT BNo,BN
FROM Book
WHERE Number > (SELECT NumberFROM BookWHERE BN = '大学计算机基础');
SELECT Book.BNo,COUNT(Borrower.RNo) AS 借阅人数
FROM Book
LEFT JOIN Borrower
ON Book.BNo = Borrower.BNo
GROUP BY Book.BNo
ORDER BY COUNT(Borrower.RNo) DESC;

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp luch-request 使用教程+响应对象创建

1. 介绍 luch-request 是一个基于 Promise 开发的 uni-app 跨平台、项目级别的请求库。它具有更小的体积、易用的 API 和方便简单的自定义能力。luch-request 支持请求和响应拦截、全局挂载、多个全局配置实例、自定义验证器、文件上传/下载、任务操作、自定义参数以及多拦截器…

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并--封装到存储过程中

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并–封装到存储过程中 我们的最终目的是什么?当然的自动执行这些合并操作! 上一篇 MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并 我们已经知道怎么合…

解决 IDEA 修改代码重启不生效的问题

前言 在使用 IntelliJ IDEA 进行 Java 项目开发时,有时会遇到一个令人头疼的问题:修改了代码后,重启服务却发现更改没有生效。通常情况下,解决这个问题需要通过 Maven 的 clean 和 compile 命令来强制重新编译,但这显…

【Mysql】Mysql函数(上)

1、概述 在Mysql中,为了提高代码重用性和隐藏实现细节,Mysql提供了很多函数。函数可以理解为封装好的模块代码。 2、分类 在Mysql中,函数非常多,主要可以分为以下几类: (1)聚合函数 &#xf…

帧中继原理与配置

Frame Relay 帧中继 LMI(Local Management Interface)本地管理接口 LMI协议通过状态查询报文和状态应答报文维护帧中继的链路状态和PVC状态. DLCI(Data Link Connection Identifier)数据链路连接标识符 DLCI只在本地接口和与之直接相连的对端接口有效,不具有全局有效性,记载帧…

Spring Boot 接口防重复提交解决方案

文章目录 前言使用Token机制实现步骤1.生成Token2.传递Token3.验证Token 使用Redis实现步骤1.引入Redis依赖2.生成Token3.传递Token4.验证Token 使用Spring AOP实现步骤1.定义注解2.创建切面3.使用注解 总结 前言 在Web开发中,防止用户重复提交表单是一个常见的需求…

【QT】解决生成的exe文件出现“无法定位程序入口”或“找不到xxx.dll”的问题

【QT】解决生成的exe文件出现“无法定位程序入口”或“找不到xxx.dll”的问题 零、问题 使用QT编译好项目后,想直接在文件资源管理器中运行exe程序或想分享出去给别人使用发现出现如下问题: 系统错误:找不到xxx.dll。 无法找到入口&#x…

Tomcat启动过程中cmd窗口(控制台)中文乱码的问题

目录 一、问题产生 二、问题分析 三、解决方法(2种) 一、问题产生 在服务器上使用新的Tomcat9(绿色版ZIP),打开一个cmd窗口后,将路径定位到“tomcat\bin\”目录,运行“startup.bat”。程序会自动打开一个新窗口,这个是Java程序的运行窗口,但是里面的中文全是乱码,如…

【MySQL】MySQL数据库入门:构建你的数据基石

🍑个人主页:Jupiter. 🚀 所属专栏:MySQL初阶探索:构建数据库基础 欢迎大家点赞收藏评论😊 目录 🦅数据库基础🐀什么是数据库🐏主流数据库🦆MySQL数据库的基本…

如何使用正则表达式验证域名

下面是一篇关于如何使用正则表达式验证域名的教程。 如何使用正则表达式验证域名 简介 域名是互联网上网站的地址,每个域名由多个标签(label)组成,标签之间用点 . 分隔。域名规则有很多细节,但基本要求是&#xff1a…

Python中的正则表达式教程

一、 正则表达式基础 1。1。概念介绍 正则表达式是用于处理字符串的强大工具,它并不是Python的一部分。 其他编程语言中也有正则表达式的概念,区别只在于不同的编程语言实现支持的语法数量不同。 它拥有自己独特的语法以及一个独立的处理引擎,在提供了正则表达式…

2024 同一个网段,反弹shell四种方法【linux版本】bash、python、nc、villian反弹shell图解步骤

实验环境准备(同一个网段下,我是桥接的虚拟机) 一、bash反弹shell 二、python反弹shell 三、nc反弹shell 四、villain反弹shell 实验环境准备(同一个网段下,我是桥接的虚拟机) 一台kali的linux(攻击者)…

Nginx server_name配置错误导致路由upstream超时问题

一、问题描述 某次本平台和外部平台接口调用,同样Nginx location配置,测试环境调用正常,生产环境调用返回失败; 相关链接:Nginx官方文档、server_name、How nginx processes a request 二、排查处理 1&#xff09…

6.584-Lab1:MapReduce

前置知识/概念 Raft 是一个基于“Leader”的协议,能够保证分布式网路的一致性。 RPC(Remote Producer Call) 参考链接1 参考链接2 Go中RPC的简单实现 Golang中regexp正则表达式的用法 https://gukaifeng.cn/posts/golang-zheng-ze-biao-…

脑机接口、嵌入式 AI 、工业级 MR、空间视频和下一代 XR 浏览器丨RTE2024 空间计算和新硬件专场回顾

这一轮硬件创新由 AI 引爆,或许最大受益者仍是 AI,因为只有硬件才能为 AI 直接获取最真实世界的数据。 在人工智能与硬件融合的新时代,实时互动技术正迎来前所未有的创新浪潮。从嵌入式系统到混合现实,从空间视频到脑机接口&…

Restful API接⼝简介及为什么要进⾏接⼝压测

一、RESTful API简介 在现代Web开发中,RESTful API已经成为一种标准的设计模式,用于构建和交互网络应用程序。本文将详细介绍RESTful API的基本概念、特点以及如何使用它来设计高效的API接口。 1. 基于协议 HTTP 或 HTTPS RESTful API通常使用HTTP&am…

面试经典 150 题:20、2、228、122

20. 有效的括号 参考代码 #include <stack>class Solution { public:bool isValid(string s) {if(s.size() < 2){ //特判&#xff1a;空字符串和一个字符的情况return false;}bool flag true;stack<char> st; //栈for(int i0; i<s.size(); i){if(s[i] ( |…

Python爬虫下载新闻,Flask展现新闻(2)

上篇讲了用Python从新闻网站上下载新闻&#xff0c;本篇讲用Flask展现新闻。关于Flask安装网上好多教程&#xff0c;不赘述。下面主要讲 HTML-Flask-数据 的关系。 简洁版 如图&#xff0c;页面简单&#xff0c;主要显示新闻标题。 分页&#xff0c;使用最简单的分页技术&…

基于Java和Vue实现的上门做饭系统上门做饭软件厨师上门app

市场前景 生活节奏加快&#xff1a;在当今快节奏的社会中&#xff0c;越来越多的人因工作忙碌、时间紧张而无法亲自下厨&#xff0c;上门做饭服务恰好满足了这部分人群的需求&#xff0c;为他们提供了便捷、高效的餐饮解决方案。个性化需求增加&#xff1a;随着人们生活水平的…

【配置后的基本使用】CMake基础知识

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;各种软件安装与配置_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1.…