MySQl 专栏持续更新 不说晦涩难懂的东西 尽量输出容易理解 和 使用的SQL技巧 和 初中级开发不是很常用的但很有用的知识
欢迎查看👉🏻👉🏻👉🏻SQL 专栏 查漏补缺 指教一二
每一次写博客对技术都会有更深入的理解 积少成多 百天计划我也想看看自己有多少成长 祝君好运 工作顺利
本文正在参加「技术专题19期 漫谈数据库技术」活动
简单
难度:
这个应该算是思路比较简单的 先创建表结构
DROP TABLE IF EXISTS `Customers`;
CREATE TABLE `Customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of Customers
-- ----------------------------
BEGIN;
INSERT INTO `Customers` (`id`, `name`) VALUES (1, '变成派大星');
INSERT INTO `Customers` (`id`, `name`) VALUES (2, '海绵宝宝');
INSERT INTO `Customers` (`id`, `name`) VALUES (3, '章鱼哥');
INSERT INTO `Customers` (`id`, `name`) VALUES (4, '蟹老板');
INSERT INTO `Customers` (`id`, `name`) VALUES (5, '路人甲');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `Orders`;
CREATE TABLE `Orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`customers_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of Orders
-- ----------------------------
BEGIN;
INSERT INTO `Orders` (`id`, `customers_id`) VALUES (1, 3);
INSERT INTO `Orders` (`id`, `customers_id`) VALUES (2, 2);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
问题
某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
示例
分析
- 两个表进行配合查询 有两种
第一个是表连接。第二个是子查询
先说表连接 关联条件是满足的 是怎么去选用 连接 方式 内链接 左连接 右连接
首先我们需要的数据是 从没有订购过的客户 也就是 Orders 不存在的 Customers 数据
- 内链接 返回相交 不合适 可以写出结果但是比较麻烦
- 右连接 返回右表数据 这个肯定是不行的 因为它只会返回 他拥有的 customers_id 但是我需要的未拥有 其实这里就可以明白 我们应该设置左表为主表 因为我们返回的信息是左表的信息
- 左链接 未匹配 数据是null 但是返回左表所有数据 这样我们就知道 右表数据为空 就是未购买的客户
左链接:
select * from Customers c left join Orders os on os.customers_id = c.id
下图中 orders 表数据为空的数据就是我们想要的
过滤:
得到结果
子查询
先查出 orders 表中的 customers_id 然后使用 Customers 进行过滤 这个思路很好理解
中等
这个难度三颗星吧 主要是如果前面练习几个题之后 思路就会好点
表结构:
DROP TABLE IF EXISTS `Logs`;
CREATE TABLE `Logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`num` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of Logs
-- ----------------------------
BEGIN;
INSERT INTO `Logs` (`id`, `num`) VALUES (1, '1');
INSERT INTO `Logs` (`id`, `num`) VALUES (2, '1');
INSERT INTO `Logs` (`id`, `num`) VALUES (3, '1');
INSERT INTO `Logs` (`id`, `num`) VALUES (4, '3');
INSERT INTO `Logs` (`id`, `num`) VALUES (5, '3');
INSERT INTO `Logs` (`id`, `num`) VALUES (6, '4');
INSERT INTO `Logs` (`id`, `num`) VALUES (7, '4');
INSERT INTO `Logs` (`id`, `num`) VALUES (8, '3');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
这个题其实挺有意思的
问题
编写一个 SQL 查询,查找所有至少连续出现三次的数字。
返回的结果表中的数据可以按 任意顺序 排列。
示例图
分析
这个主要的难点在于 连续 且相等 如果仅仅是出现次数大于等于三次的 我们可以直接 通过 having 进行过滤 但是要想找到连续的就要进行运算比较 前面练习过的数据 我们知道一个表数据中 进行数据比较 可以去使用自连接 id 因为是自增的 连续的id 就说明 每行相差 1 这两个思路比较重要 至少大于 3 就需要自连接两次 将三张表的数据进行比较
先筛选出相等三张表中相等的数据
-- 三张表连接 会有 8*8*8 = 512 条数据
select * FROM Logs l1,Logs l2,Logs l3
-- 筛选出 num 相同的数据 62条
select * FROM Logs l1,Logs l2,Logs l3 where l1.num = l2.num and l2.num = l3.num
筛选完成之后还剩余 62 条 接下来根据 id 连续来进行筛选 Id 是否连续 需要通过列运算 如下写法:
-- 当超过 3个连续相同的会有 重复数据 所有需要去重
select DISTINCT l1.num AS ConsecutiveNums FROM Logs l1,Logs l2,Logs l3 where l1.num = l2.num and l2.num = l3.num and l3.id = l2.id + 1 and l2.id = l1.id + 1
上面这种写法 比较中规中矩 还有一种很有意思的写法 使用子查询 这种写法相对来说比较有意思
SELECT DISTINCT Num AS ConsecutiveNums FROM Logs
WHERE (id+1, num) IN (SELECT * FROM Logs)
AND (id+2, num) IN (SELECT * FROM Logs)
-- 相当于
SELECT DISTINCT Num AS ConsecutiveNums FROM Logs
WHERE (1+1, 1) IN (SELECT * FROM Logs)
AND (1+2, 1) IN (SELECT * FROM Logs)
结尾
着实有点忙 第三题非找个困难的搞一搞 先让他跑一会
本文正在参加「技术专题19期 漫谈数据库技术」活动