likes
comments
collection
share

SQL思维训练

作者站长头像
站长
· 阅读数 11

前言

从十月二十四号给自己定下目标 每天坚持学习东西 第一站是MySQL 最近也写了几篇文章 今天突然感觉需要进行练习 以后每天更新 三道SQL题进行思维训练 一步步走 感觉简单的 都有点绕 真的是训练少啊

简单

难度:

这个难度不高 但是初中级感觉还是要思考一会 先说一下问题

创建表结构

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for person
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES (1, 'hugh@163.com');

INSERT INTO `person` VALUES (2, 'hugh@163.com');

INSERT INTO `person` VALUES (3, 'sun@163.com');
SET FOREIGN_KEY_CHECKS = 1;

问题

编写一个 SQL 删除语句删除 所有重复的电子邮件,只保留一个id最小的唯一电子邮件。

任意顺序 返回结果表。 (注意: 仅需要写删除语句,将自动对剩余结果进行查询)

示例

SQL思维训练

分析

其实这个只要能想到怎么去将相同的数据找出来 并且比较 哪一个大哪一个小 返回大的数据进行删除就行了 问题是删除相同的数据 相同就是一个关键点 遇到这种一张表 进行比较处理的时候 我们应该想到的是自连接 自连接的概念之前文章也有说过 自连接就是可以将一张表中的数据拆开使用 但是表连接都需要一个相等字段 也就是邮箱

先自连接一下

SELECT * from person ps join person pn on ps.email = pn.email

SQL思维训练

上图返回了五条数据 就是这表中数据 的组合 我们下面需要找 表1 和 表 2 之间 相同数据 ID 较大的部分

SQL思维训练

SQL思维训练

查出这一条最大的直接删除就行了

DELETE ps from person ps join person pn on ps.email = pn.email and ps.id > pn.id

SQL思维训练

小感悟

在进行一张表的数据比较的时候就可以考虑自连接 进行数据处理

简单

难度:

问题

找出下表中超过经理收入的员工

准备表

  • id 是主键
  • name 是姓名
  • salary 是工资
  • managerId 经理
CREATE TABLE Employee(
id BIGINT PRIMARY KEY auto_increment,
name VARCHAR(30) not null,
salary DECIMAL,
managerId BIGINT
)

分析

同样是一个表比较 经过上一题 你应该很明白 就是直接进行自连接 然后经理和员工的工资进行比较

select e1.name as employee
    from employee e1, employee e2
        where e1.managerid = e2.id 
            and e1.salary > e2.salary;
复制代码

SQL思维训练

中等

难度:

创建表结构:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for scores
-- ----------------------------
DROP TABLE IF EXISTS `scores`;
CREATE TABLE `scores`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `score` decimal(10, 0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of scores
-- ----------------------------
INSERT INTO `scores` VALUES (1, 23);
INSERT INTO `scores` VALUES (2, 23);
INSERT INTO `scores` VALUES (3, 34);
INSERT INTO `scores` VALUES (4, 12);
INSERT INTO `scores` VALUES (5, 45);
INSERT INTO `scores` VALUES (6, 34);
INSERT INTO `scores` VALUES (7, 33);
SET FOREIGN_KEY_CHECKS = 1;

问题

编写 SQL 查询对分数进行排序。排名按以下规则计算:

  • 分数应按从高到低排列。
  • 如果两个分数相等,那么两个分数的排名应该相同。
  • 在排名相同的分数后,排名数应该是下一个连续的整数。换句话说,排名之间不应该有空缺的数字。

按 score 降序返回结果表

示例

SQL思维训练

懵逼树上懵逼果 懵逼树下你和我 刚看到真是 我在干嘛 我看不懂 但是分析一波

分析

先再分析一下排序

SQL思维训练

首先还是一张表 还是一张表进行表比较 至少我能立马想到几点

  • 一张表 表比较 可以使用自连接 上面刚用过
  • 分数从高到低进行排列 order By 咱也懂
  • 相同分数排名相同 我也懂 至少字面意思明白了
  • 排名连续 字面意思也懂了

古人云 柿子要挑软的捏 先来会的 自连接

select s1.id ,s1.score AS 表1,s2.id ,s2.score As 表二 from scores s1 join scores s2

原数据 七条 自连接之后 49 每条数据对应七条 SQL思维训练

比如:

SQL思维训练

上面再分析的时候我们知道 排序就是通过比较 45 和 其余几个数据分别比较 有几个大于等于他 他就排第几

我们这个时候就可以写新的SQL

select s1.id ,s1.score AS 表1,s2.id ,s2.score As 表二 from scores s1 join scores s2 where  s1.score <= s2.score

现在还剩下30条 我们可以看到有很多ID重复的 我们Group By 一下

SQL思维训练

这个时候 s1 的分数排序 取决于 s2 中的数据 也就是group by的数据 我们通过count 看一下

select s1.Score, COUNT(DISTINCT s2.Score) AS `RANK` from scores s1 join scores s2 where  s1.score <= s2.score GROUP BY s1.id order by `RANK`

SQL思维训练

如果还有朋友不明白再看一点

SQL思维训练

也就是 s1 中 33 小于 这七条数据中的三个 34 34 45

小感悟

单表比较自连接 香的很

总结

原本想 简单 中等 困难的 但是困难实在太困难了 还是慢慢来 这个三个题刚好都是自联结 可以好好思考一下 不知道大家能解出几个 哈哈哈哈

疯狂星期四 文章完结

  • 如果你是直接跳到这里 看看文章有多长 建议收藏
  • 如果你一步步看到这里 感觉有点帮助 赞赞来一个
  • 如果感觉文章有问题 建议评论区指出 会修正

持续更新SQL相关系列 可追更 不可催更

SQL思维训练