SQL思维训练
前言
从十月二十四号给自己定下目标 每天坚持学习东西 第一站是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最小的唯一电子邮件。
以 任意顺序 返回结果表。 (注意: 仅需要写删除语句,将自动对剩余结果进行查询)
示例
分析
其实这个只要能想到怎么去将相同的数据找出来 并且比较 哪一个大哪一个小 返回大的数据进行删除就行了 问题是删除相同的数据 相同就是一个关键点
遇到这种一张表 进行比较处理的时候 我们应该想到的是自连接 自连接的概念之前文章也有说过 自连接就是可以将一张表中的数据拆开使用 但是表连接都需要一个相等字段 也就是邮箱
先自连接一下
SELECT * from person ps join person pn on ps.email = pn.email
上图返回了五条数据 就是这表中数据 的组合 我们下面需要找 表1 和 表 2 之间 相同数据 ID 较大的部分
查出这一条最大的直接删除就行了
DELETE ps from person ps join person pn on ps.email = pn.email and ps.id > pn.id
小感悟
在进行一张表的数据比较的时候就可以考虑自连接 进行数据处理
简单
难度:
问题
找出下表中超过经理收入的员工
准备表
- 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;
复制代码
中等
难度:
创建表结构:
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
降序返回结果表
示例
懵逼树上懵逼果 懵逼树下你和我 刚看到真是 我在干嘛 我看不懂 但是分析一波
分析
先再分析一下排序
首先还是一张表 还是一张表进行表比较 至少我能立马想到几点
- 一张表 表比较 可以使用
自连接
上面刚用过 - 分数从高到低进行排列
order By
咱也懂 - 相同分数排名相同 我也懂 至少字面意思明白了
- 排名连续 字面意思也懂了
古人云 柿子要挑软的捏 先来会的 自连接
select s1.id ,s1.score AS 表1,s2.id ,s2.score As 表二 from scores s1 join scores s2
原数据 七条 自连接之后 49 每条数据对应七条
比如:
上面再分析的时候我们知道 排序就是通过比较 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 一下
这个时候 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`
如果还有朋友不明白再看一点
也就是 s1 中 33 小于 这七条数据中的三个 34 34 45
小感悟
单表比较自连接 香的很
总结
原本想 简单 中等 困难的 但是困难实在太困难了 还是慢慢来 这个三个题刚好都是自联结 可以好好思考一下 不知道大家能解出几个 哈哈哈哈
疯狂星期四 文章完结
- 如果你是直接跳到这里 看看文章有多长
建议收藏
- 如果你一步步看到这里 感觉有点帮助
赞赞来一个
- 如果感觉文章有问题 建议评论区指出
会修正
持续更新SQL相关系列 可追更 不可催更
转载自:https://juejin.cn/post/7164386115909058574