也没啥, 就是入坑 sql 根本停不下来, 势必要达到所谓 "精通" 的地步.

从网上的例子也快搬运完了, 而工作中的 sql 又是万万不能外泄了. 因此想着, 该去哪里搬砖呢, 是有想刷 LeetCode 的冲动, 如果工作的 SB 客户, 不要那么为难我, 搞那些变态的需求, 不然我得挂掉了, 再跟他们这样玩下去的话. 还是抓紧练习 SQL, 万物皆 SQL. 我是万物. 虽然都是些简单的题, 反复练习, 其实也是在接近本质了, 但愿如此, 一步步这样一直走下去, 永不回头.

今天的 sql 练习, 就一题, 然后整一波, 4张表关联, 写套娃.... 一层套一层的那种, 从 a, b, c, d, e, f, g , 层层套,厉害了.

表关系

需求 01

查询 不同课程成绩相同 的学生的 学号, 课程号, 课程名称, 成绩

分析

不同成绩相同的 学号 ... 即对 学号, 成绩 进行 group by 即可, 然后再 inner join 上缺失的字段.

select
s_id,
score from score
group by s_id, score
+------+-------+
| s_id | score |
+------+-------+
| 0001 | 80 |
| 0001 | 90 |
| 0001 | 99 |
| 0002 | 60 |
| 0002 | 80
|
| 0003 | 80 |
+------+-------+
6 rows in set (0.01 sec)

发现, 就只要 0 3 号兄弟是满足要求的, 因为是用 s_id 和 score 来做 group by 的, 003 只出现一次, 说明, 要么他就只是选了一门课, 要么就是 他选的课, 分数都是一样的, 这样才会出现 一条 记录呀. 要的就是它, 给他 having 筛选出

select
s_id,
score
from
(
select
s_id,
score
from score
group by s_id, score
) as a group by s_id having count(s_id) = 1
+------+-------+
| s_id | score |
+------+-------+
| 0003 | 80 |
+------+-------+
1 row in set (0.00 sec)

还要排除一种情况是, 当他只选了一种可的情况. 即我们真正需要的 s_id 还需要满足这个条件

-- 选课数必须 大于 1
select s_id from score
group by s_id having count(distinct c_id) > 1
+------+
| s_id |
+------+
| 0001 |
| 0002 |
| 0003 |
+------+
3 rows in set (0.00 sec)

将这个条件给加进去, 当然不用 in 这种子查询方式啦, inner join 即可

select
b.s_id,
b.score from
(
select
s_id,
score
from
(
select
s_id,
score
from score
group by s_id, score
) as a group by s_id having count(s_id) = 1 ) as b -- 添加条件给 s_id
inner join (
select s_id from score
group by s_id having count(distinct c_id) > 1 ) as c on b.s_id = c.s_id
+------+-------+
| s_id | score |
+------+-------+
| 0003 | 80 |
+------+-------+
1 row in set (0.00 sec)

这个逻辑就会有点稍微复杂了.

select
b.s_id,
d.s_name,
b.score from
(
select
s_id,
score
from
(
select
s_id,
score
from score
group by s_id, score
) as a group by s_id having count(s_id) = 1 ) as b -- 添加条件给 s_id
inner join (
select s_id from score
group by s_id having count(distinct c_id) > 1
) as c
on b.s_id = c.s_id -- 再将学生的信息给 匹配上来
inner join student as d
on c.s_id = d.s_id
+------+-----------+-------+
| s_id | s_name | score |
+------+-----------+-------+
| 0003 | 胡小适 | 80 |
+------+-----------+-------+
1 row in set (0.00 sec)

呀, 还没有完, 还要根据 这个 s_id 去 score 中 查出 选的 c_id, 再根据 c_id 从 course 中查出 c_name.

也是通过 join 的方式, 首先将这个结果集, 弄个套娃, inner join 和 成绩表, 再 inner join 课程表.

select
f.s_id,
e.s_name,
f.c_id,
g.c_name,
e.score from
(
select
b.s_id,
d.s_name,
b.score from
(
select
s_id,
score
from
(
select
s_id,
score
from score
group by s_id, score
) as a group by s_id having count(s_id) = 1 ) as b -- 添加条件给 s_id
inner join (
select s_id from score
group by s_id having count(distinct c_id) > 1
) as c
on b.s_id = c.s_id -- 再将学生的信息给 匹配上来
inner join student as d
on c.s_id = d.s_id
) as e -- 匹配上相关的课程id
inner join score as f
on e.s_id = f.s_id -- 匹配上相关的课程名称
inner join course as g
on f.c_id = g.c_id
+------+-----------+------+--------+-------+
| s_id | s_name | c_id | c_name | score |
+------+-----------+------+--------+-------+
| 0003 | 胡小适 | 0001 | 语文 | 80 |
| 0003 | 胡小适 | 0002 | 数学 | 80 |
| 0003 | 胡小适 | 0003 | 英语 | 80 |
+------+-----------+------+--------+-------+
3 rows in set (0.00 sec)

这个套娃, 就有点东西了,我也是不是一下子写出来的, 跟我平时写代码一样, 一边调试, 一边写. 一点点给堆上去的, 果然写代码, 写sql 都是一样的, 就是搬砖, 一点点往上堆就行了. 惨痛的经验告诉我, 如果事先整体的架构没有搭好, 后面的改动起来就非常麻烦了.

小结

  • 写 sql 套娃, 确实是非常锻炼逻辑能力的时刻, 当然我从不考虑性能, 能做出来已经很不错了, 除非真的特别慢
  • join 和 子查询相互配合使用, 我现在是更加偏向用 join 多一些, 子查询部分, 体现在 中间的查询集中
  • 理清楚整个的逻辑和 代码缩减编排, 可读性上, 我觉得很关键, 不然别人看这就是一堆乱码, 理不清楚, 我现在的风格, 就多别名的那种, 从小写字母 a,b,c,d,e... 这样一直编, 跟着这个逻辑看下去, 肯定没啥问题的.

SQL 日常练习 (十八)的更多相关文章

  1. SQL语句(十八_补充)——存储过程

    一. 变量 1. 形式: @x (局部), @@x(全局) 2. 定义: declare @x 3. 赋值:Set @x = ? 4. 作用: 通用化 存储在服务器 5. 存储过程(预编译过的T-SQ ...

  2. SQL语句(十八)—— 存储过程

    存储过程 系统存储过程 自定义存储过程 扩展存储过程 一.创建存储过程 创建存储过程 --例1 USE SU GO Create Procedure SelProc AS Select * From ...

  3. SQL注入之Sqli-labs系列第四十七关,第四十八关,第四十九关(ORDER BY注入)

    0x1 源码区别点 将id变为字符型:$sql = "SELECT * FROM users ORDER BY '$id'"; 0x2实例测试 (1)and rand相结合的方式 ...

  4. SQL注入之Sqli-labs系列第三十八关、第三十九关,第四十关(堆叠注入)

    0x1 堆叠注入讲解 (1)前言 国内有的称为堆查询注入,也有称之为堆叠注入.个人认为称之为堆叠注入更为准确.堆叠注入为攻击者提供了很多的攻击手段,通过添加一个新 的查询或者终止查询,可以达到修改数据 ...

  5. MyBatis基础入门《十八》动态SQL(if-where)

    MyBatis基础入门<十八>动态SQL(if-where) 描述: 代码是在<MyBatis基础入门<十七>动态SQL>基础上进行改造的,不再贴所有代码,仅贴改动 ...

  6. SQL注入之Sqli-labs系列第十八关(基于错误的用户代理,头部POST注入)

    开始挑战第十八关(Header Injection - Uagent field - Error based) 常见的HTTP注入点产生位置为[Referer].[X-Forwarded-For].[ ...

  7. SQL注入之Sqli-labs系列第二十八关(过滤空格、注释符、union select)和第二十八A关

    开始挑战第二十八关(Trick with SELECT & UNION) 第二十八A关(Trick with SELECT & UNION) 0x1看看源代码 (1)与27关一样,只是 ...

  8. 最全的MySQL基础【燕十八传世】

    1.课前准备! 开启mysql服务:1).配置环境变量;2).net start mysql 将该sql文件导入到你的数据库中,以下所有操作都是基于该数据库表操作的!!! [此笔记是本人看着视频加上自 ...

  9. VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器

                        VMware vSphere 服务器虚拟化之十八桌面虚拟化之安装View Composer服务器      View Compose服务可安装在管理虚拟机的vC ...

  10. 会员卡管理系统技术解析(十八)Timer定时监听

    会员卡管理系统技术解析(十八)Timer定时监听 在web应用中,有时候客户须要一些定时程序.不须要客户自己去操作.而是由应用程序自行触发(代理)运行某些操作. 这个时候监听与定时器的配合使用就基本能 ...

随机推荐

  1. Common.Logging+log4net搭建项目日志框架

    原文参考链接:https://www.cnblogs.com/heys/p/5787123.html   Common.Logging+(log4net/NLog/) common logging是一 ...

  2. 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?

    你好呀,我是歪歪. 事情是这样的,前几天有一个读者给我发消息,说他面试的时候遇到一个奇形怪状的面试题. 歪师傅纵横面试界多年,最喜欢的是奇形怪状的面试题. 可以说是见过大场面的人,所以让他描述一下具体 ...

  3. 离线环境安装nodejs及npm库i5ting_toc(超详细,手把手教学一通百通)

    一.离线环境先安装nodejs   1.在可联网的电脑上下载特定版本的 Node.js: 访问 Node.js 官方下载页面(https://nodejs.org/download/release/) ...

  4. xbox商店访问、下载速度慢,如何提升下载速度?

    Xbox下载速度慢可能是由于多种原因,例如网络连接问题.微软服务器问题等.以下是一些可以尝试的方法来提升Xbox的下载速度: 更改网络设置:以WIN11举例:鼠标右键点电脑桌面右下角的网络图标,选择& ...

  5. Azure Data Factory - [01] 触发器

    题记部分 一.概述   Azure Data Factory(后面简称ADF)的触发器是一种机制,用于在特定事件发生时自动执行数据管道.触发器可以基于事件间隔.数据变化或其他外部事件来启动数据管道的执 ...

  6. js回忆录(4) -- 对象,构造函数

    1.对象 && 构造函数 js是一门基于对象的语言,里边所有的数据类型都可以当对象使唤(当然null和undefined除外),当我们在v8引擎里声明一个对象时会发现每个对象属性里边都 ...

  7. mac上 Kratos 配置 protoc

    前言 protoc 是 protobuf 文件(.proto)的编译器,可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,包含数据类型定义.调用接口等. protoc 在设计上把 p ...

  8. 查看、安装python指定版本的包、安装卸载第三方模块

    python安装/卸载第三方包 (1)安装第三方包: 安装指令pip install xxx (xxx,需安装的包名) 安装特定版本的package:通过使用==, >=, <=, > ...

  9. C#通过FTP获取服务端文件

    一.简介   实际需求是在前端修改了配置文件后,由上位机统一分发给所有设备,因为下位机支持FTP协议,因此选用FTP来实现文件传输功能. 二.准备工作 1.FTP服务搭建 FTP服务端选用FileZi ...

  10. Vue3封装支持Base64导出的电子签名组件

    效果图 准备工作 组件内用到elementPlus,vue-esign组件,使用前提前安装好. 组件代码 <template> <!-- 签名容器 --> <div cl ...