当然, 说明一下, 所有的内容都是网上搬砖的, 也是用作自己练习用的.

我觉得如何去写 sql 这个思考的过程, 远比最终写出来更重要, 毕竟, 我最近有在公司看到了 2000多行的一个 sql. 我觉的, 这样神级的存在, 也是, 九层之台,起于垒土. 而最为重要的是理清楚逻辑. 我最真实的情况是, 一般在做一些数据处理的时候, 我用 pandas 几乎能完成任何的数据操作. 根本原因在于,我头脑中, 始终有一个 DataFrame 的影像. 我始终能知道我当前的对象, 会是怎样的 DataFrame. 而这点是我在 SQL 所不具备的. 因而, 我觉得, sql 的思路过程, 会帮助我去理解这一块.

数据关系

这个是都次都要重复提及的. 只有熟练知晓表结构, 才能做各种查询呀.

需求

第 01 题

查询课程编号为 "0001" 的课程, 比 "0002" 的课程成绩 高 的所有学生的 学号.

分析

可以从面向过程的角度, 其实, 如果我们有这样的一张表.

s_id, c_id_0001_score, c_id_0002_score

s_a, 90, 80
s_b, 80, 60
s_c, 70, 98 -- 则就简单了直接
select s_id from xxx where c_id_0001 > c_id_0002;

即涉及的表主要是 score 表.

mysql> select * from score;
+------+------+-------+
| s_id | c_id | score |
+------+------+-------+
| 0001 | 0001 | 80 |
| 0001 | 0002 | 90 |
| 0001 | 0003 | 99 |
| 0002 | 0002 | 60 |
| 0002 | 0003 | 80 |
| 0003 | 0001 | 80 |
| 0003 | 0002 | 80 |
| 0003 | 0003 | 80 |
+------+------+-------+
8 rows in set (0.00 sec)

可以看到, 1, 3号学生有选1,2,3 课程; 2号学生选了 2,3 号课程.

如果要给 2号学生选上1号课, 则:

insert into score values ("0002", "0001", 85)

要想得到咱上面 的表呢, 其实就是, 将这里的 score:

  • 以 c_id 分为 0001 和 0002 两个部分,
  • 以 s_id 作为键, 对这两部分进行 inner join 即可.
-- 首先从 score 找出 课程为 0001 的 学生id, 课程id, 和成绩
select
s_id,
c_id,
score
from score
where
c_id = "0001";
+------+------+-------+
| s_id | c_id | score |
+------+------+-------+
| 0001 | 0001 | 80 |
| 0003 | 0001 | 80 |
+------+------+-------+
2 rows in set (0.00 sec)

可以看到, 选择课程 0001 的有 1, 3号学生, 他们的成绩都是80

-- 同样从 score 中找出课程为0002的s_id, c_id, score
select
s_id,
c_id,
score
from score
where
c_id = "0002";
+------+------+-------+
| s_id | c_id | score |
+------+------+-------+
| 0001 | 0002 | 90 |
| 0002 | 0002 | 60 |
| 0003 | 0002 | 80 |
+------+------+-------+
3 rows in set (0.00 sec)

选课 0002 课程的有 1,2,3 号学生, 成绩分别为 90, 60, 80

要查询课程编号为 "0001" 的课程, 比 "0002" 的课程成绩 高 的所有学生的 学号. 其实就将这两个查询集, 给 inner join 就好了呀.


-- 外面需要再套一层
select *
from
(
select
s_id,
c_id,
score
from score
where
c_id = "0001"
) as a
-- 连接方式
inner join
(
select
s_id,
c_id,
score
from score
where c_id = "0002"
) as b -- 连接条件
on
a.s_id = b.s_id;

可以看到, 其实 0001 > 0002 的兄弟, 是没有的.

+------+------+-------+------+------+-------+
| s_id | c_id | score | s_id | c_id | score |
+------+------+-------+------+------+-------+
| 0001 | 0001 | 80 | 0001 | 0002 | 90 |
| 0003 | 0001 | 80 | 0003 | 0002 | 80 |
+------+------+-------+------+------+-------+
2 rows in set (0.01 sec)

为了有, 我把条件给放宽到 等于吧, 即 3号兄弟, 然后完整地来写一遍 sql

select
a.s_id as "学号"
-- a.score as "0001课的成绩",
-- b.score as "0002棵的成绩"
from
(
select
s_id,
c_id,
score
from score
where
c_id = "0001"
) as a
-- 连接方式
inner join
(
select
s_id,
c_id,
score
from score
where c_id = "0002"
) as b -- 连接条件
on
a.s_id = b.s_id
where
a.score >= b.score;

这样就只查到了学号

+--------+

| 学号 |

+--------+

| 0003 |

+--------+

1 row in set (0.00 sec)

假如我们这里再来扩展一波, 不仅要学号, 还要姓名的话, 就需要再 inner join 学生表了呀, 根据 s_id

select
a.s_id as "学号",
c.s_name as "学生姓名",
a.score as "0001课的成绩",
b.score as "0002棵的成绩"
from
(
select
s_id,
c_id,
score
from score
where
c_id = "0001"
) as a
-- 连接方式
inner join
(
select
s_id,
c_id,
score
from score
where c_id = "0002"
) as b -- 连接条件
on
a.s_id = b.s_id -- 补充上学生的名字
inner join student as c
on c.s_id = a.s_id where
a.score >= b.score;

然后就可以看到3号的老铁啦

+--------+--------------+------------------+------------------+
| 学号 | 学生姓名 | 0001课的成绩 | 0002棵的成绩 |
+--------+--------------+------------------+------------------+
| 0003 | 胡小适 | 80 | 80 |
+--------+--------------+------------------+------------------+
1 row in set (0.01 sec)

可以看到, 我们这里的学号是 1对1 的, 如果是多对多什么的, 感觉就会比较复杂了.

小结

  • 这个demo 的关键思路是, 将 score 通过课程 id 的方式给分成 几份, 做内连接
  • 整个写法呢, 是面向过程的, 应用子查询来弄
  • 代码排版上, 尽量能分块, 缩进, 提高阅读体验

虽然这一篇就只是弄了一个 sql 但我感觉, 涉及的东西还是挺多的, 尤其是最初的那个假定的表, 思维这块需要多练.

SQL 强化练习 (一)的更多相关文章

  1. SQL强化(一)保险业务

    保险业务 : 表结构 : sql语句 : /*1. 根据投保人电话查询出投保人 姓名 身份证号 所有保单 编号 险种 缴费类型*/SELECTt2.cust_name,t2.idcard,t4.pro ...

  2. SQL强化练习(面试与学习必备)

    一.经典选课题A 1.1.请同时使用GUI手动与SQL指令的形式创建数据库.表并添加数据. 题目:设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教 ...

  3. SQL强化(三) 自定义函数

    ---恢复内容开始--- Oracle中我们可以通过自定义函数去做一些逻辑判断,这样可以减少查询语句,提高开发效率 create  -- 创建自定义函数 or replace -- 有同名函数就替换, ...

  4. SQL强化(二) 在Oracle 中写代码

    一  : 关于查询中的转换 -- 字符串转换 一 : decode 函数 转换 SELECT DECODE ( PROTYPE.PRO_TYPE_DATE, 'L', '长', 'm', '短', ' ...

  5. 基本的sql 语句

    1,登陆数据库:mysql -u root -p2,退出数据库:exit quit ctr+d3,创建数据库:create database 数据库名 charset=utf84,使用数据库:use ...

  6. 数据库语言sql

    数据库语言SQL SQL的形式 交互式SQL 一般DBMS都提供联机交互工具 用户可直接键入SQL命令对数据库进行操作 由DBMS来进行解释 嵌入式SQL 能将SQL语句嵌入到高级语言(宿主语言) 使 ...

  7. MySQL数据库SQL语法常规操作

    必备sql和表关系及授权 graph LR 执行1[必备sql和授权] 执行2[SQL强化和实践] 执行3[索引和函数以及存储过程] 执行4[Python操作mysql和应用] 执行5[常见SQL语句 ...

  8. 一个小时学会MySQL数据库

    随着移动互联网的结束与人工智能的到来大数据变成越来越重要,下一个成功者应该是拥有海量数据的,数据与数据库你应该知道. 一.数据库概要 数据库(Database)是存储与管理数据的软件系统,就像一个存入 ...

  9. [工具]K8tools github/K8工具合集/K8网盘

    K8tools 20190428 声明: 工具仅供安全研究或授权渗透,非法用途后果自负. 博客: https://www.cnblogs.com/k8gege 下载: https://github.c ...

  10. 【转载】一个小时学会MySQL数据库

    一个小时学会MySQL数据库   目录 一.数据库概要 1.1.发展历史 1.1.1.人工处理阶段 1.1.2.文件系统 1.1.3.数据库管理系统 1.2.常见数据库技术品牌.服务与架构 1.3.数 ...

随机推荐

  1. 安川Yaskawa机器人DX100示教器维修的优劣势分析

    安川Yaskawa机器人DX100示教器维修的优劣势分析 安川Yaskawa机器人示教编程,即操作人员经过安川机器人示教器,手动操控机器人的关节运动,以使机器人运动到预订的方位,一起将该方位进行记载, ...

  2. autohue.js:让你的图片和背景融为一体,绝了!

    需求 先来看这样一个场景,拿一个网站举例 这里有一个常见的网站 banner 图容器,大小为为 1910*560 ,看起来背景图完美的充满了宽度,但是图片原始大小时,却是: 它的宽度只有 1440 , ...

  3. SpringBoot实现HandlerInterceptor拦截器的接口没有需要重写的方法也不报错是怎么回事

    以前实现HandlerInterceptor接口,总会提示需要实现3个方法(preHandle.postHandle.afterCompletion).现在没有出现提示.原因:这是Java8的新特性- ...

  4. JNZ项目犯错记

    年度绩效因为JNZ项目没有达到绩效目标被打了低绩效,这个是我从业这么多年来第一次低绩效,记一下我在这个项目中犯的错误. 项目起源 公司业务是一个ToB的电商场景,已经经营数年了,公司会给大客户一定账期 ...

  5. [AI/GPT/Chat2SQL/RAG] VannaAI

    概述:VaanaAI 缘起 使用 AI 生成 SQL 的原因 数据仓库和数据湖在企业中广泛应用,但能够精通 SQL 并理解企业数据结构的人很少.AI 可以帮助商业用户使用自然语言查询数据库,生成 SQ ...

  6. STM32实战——DHT11温湿度获取并展示

    介绍 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,包括一个电阻式感湿元件和一个NTC测温元件,可以用来测量温度和湿度. 硬件连线 注意 本实验使用STM32F103C8T ...

  7. 赶快检查,木马可能已经植入服务器,Redis未授权访问漏洞记录,redis的key值出现backup要谨慎

    问题描述:为图省事,很多时候我们在使用redis的时候会使用默认空密码,这就增加了安全隐患,如果有下属情况,那赶快去检查下redis,木马或许已经植入服务器,应尽快处理: 1.redis绑定在 0.0 ...

  8. 震惊!Manus邀请码炒到5万元一个!附免费获取Manus邀请码两种方式

    在AI技术蓬勃发展的当下,一款名为Manus的产品掀起了行业巨浪.本文将深入剖析这款全球首款通用AI智能体,从它的惊艳亮相.独特功能,到其性能突破.模式限制,以及在AI领域的深远意义,全方位带大家了解 ...

  9. SpringBoot集成WebServlet出现自定义单servlet请求失败的问题

    一.导言 SpringBoot的真正核心是快速整合以及自动装配,所以在spring家族中springBoot不仅整合了Spring的IOC容器还兼容了WebServlet容器:这使得springBoo ...

  10. PHP的回调函数

    所谓的回调函数,就是指调用函数时并不是向函数中传递一个标准的变量作为参数,而是将另一个函数作为参数传递到调用的函数中,这个作为参数的函数就是回调函数.通俗的来说,回调函数也是一个我们定义的函数,但是不 ...