您现在的位置是:亿华云 > 系统运维
从 LeetCode 的题目再看 MySQL Explain
亿华云2025-10-09 15:23:19【系统运维】9人已围观
简介本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。今天阿粉主要是想通过 LeetCode 上面的一个题目来再带大家看看 MySQL 的变量使用以及通过 E
本文转载自微信公众号「Java极客技术」,题目作者鸭血粉丝 。题目转载本文请联系Java极客技术公众号。题目
今天阿粉主要是题目想通过 LeetCode 上面的一个题目来再带大家看看 MySQL 的变量使用以及通过 Explain 的解析看看SQL 的执行过程。虽然平时在工作中对于 MySQL 使用的题目很多,但是题目相对于 MySQL 的变量使用相对还是较少的,所以阿粉在刚看到的题目时候还是有点懵的,不过我相信大家肯定不会像阿粉一样,题目毕竟能关注我们公众号的题目读者都是优秀的。
题目
题目描述:编写一个 SQL 查询,题目查找所有至少连续出现三次的题目数字。并且给了一个示例,题目阿粉按照题目给的题目示例在本地创建了 Logs 表和插入相应的数据,如下:
我们可以看到在给定上面的题目 Logs 表中,免费信息发布网 1 是题目唯一连续出现至少三次的数字,所以最后输出的结果是 1。
原始题目:LeetCode 180
刚看到题目的时候,阿粉一瞬间还是没反应过来,不知道该如何着手进行,思索了一下考虑是否可以用自连接来实现呢?然后根据题目的意思就写出了如下的 SQL。
SELECT DISTINCT l1.num FROM `Logs` l1, `Logs` l2, `Logs` l3 WHERE l1.num = l2.num AND l2.num = l3.num AND l1.id = l2.id - 1 AND l2.id = l3.id - 1写完过后阿粉第一次提交,提示下面错误,可以看到是最后没有将返回重命名,调整了一下 SQL,就l1.num 改成l1.num as ConsecutiveNums 再次提交,得到的第二张通过的图。
看开始看到通过,阿粉还在想这道题也没什么啊,还是 so easy 的嘛。但是突然阿粉转念一想,这个题目说的是企商汇连续出现,并没有说 ID 是连续的啊,如果 ID 不连续的话,这种就不对了,还有就是如果需要连续 4 次出现的,5 次出现的数字呢?总不能一直自连接下去吧。如果写成这样那整个 SQL 就太不灵活了。
随后阿粉就看了一下官方解答以及相关评论,果不其然虽然官方给出的解答跟阿粉的一致,但是下面的评论却有很多小伙伴都在说这个 ID 不连续的问题。
既然反馈这种做法有问题,那自然就会有好事之者会想到解决办法,果然评论区的一个大佬给出了下面的这种解法
刚看到这个解法的时候,阿粉一下子没有看懂,把这个代码进行了提交,果然也是正常的通过了。而且这种解法不会被出现几次的站群服务器条件给限制。抱着学习的心态,阿粉准备研究一下这条 SQL 里面的内容。
SQL 拆解
首先这条 SQL 里面有这么几个地方让阿粉迷惑,第一个是@ 符号,然后是:= 然后还有个 case when then 语法,平日里在 CRUD 的时候没遇到过这种写法,不过不知道没关系,Google 一下就好了。网上查了下,@prev 表示的是声明变量,:=操作是 MySQL 的赋值操作,case when then when 后面接的是判断条件,条件成立则会返回then 后面的结果,需要注意的是 case 只会返回第一个符合条件的结果,剩下将会被忽略。
简单的了解了上面几个知识点过后,我们就可以对下面这条 SQL 进行拆解了。
select distinct Num as ConsecutiveNums from ( select Num, case when @currnet = Num then @count := @count + 1 when (@currnet := Num) is not null then @count := 1 end as CNT from Logs, (select @currnet := null,@count := 0) as t ) as temp where temp.CNT >= 3 最外层的 select distinct Num as ConsecutiveNums from () as temp where temp.CNT >= 3 ; 我们可以看到中间的小括号里面被派生成了一个临时表,表名叫做 temp,并且 temp 表中有两个字段分别是Num,CNT。其实Num 则是表Logs 里面的数字,CNT 则是连续出现的累积次数,最后的where temp.CNT >= 3 则是在根据要求连续出现的次数进行查询。 派生语句SELECT Num,CASE WHEN @currnet=Num THEN @count:=@count+1 WHEN (@currnet:=Num) IS NOT NULL THEN @count:=1 END AS CNT FROM LOGS,(SELECT @currnet:=NULL,@count:=NULL) AS t 包含两个部分,一个是Select 中的case when then 另一个是from 中的 (select @currnet:= null,@count := null) as t 其中select @currnet:= null,@count := null 也是一个派生表,这里通过声明两个变量@currnet, @count 并赋值为null 。 中间派生的表 temp 的内容如下,通过生成记录每个数字出现的次数的临时表来查询数据。下面我们通过explain 命令看下整个 SQL 的执行过程,:
不得不说,上面的方案是很完美的,不存在 ID 是否连续的问题,也不会多层自连接,而且也可以根据要求找出连续出现的次数,相对灵活。刚开始看到这个 SQL 的时候,阿粉并不清楚整个执行的过程,然后通过 explain 才渐渐明白整个执行过程, 而且对于在 SQL 中使用变量也有了一定的了解。
很赞哦!(1)
相关文章
- 在更换域名后,并不是就万事大吉了,我们需要将旧域名做301重定向到新域名上,转移旧域名的权重到新域名上。
- 华为推出原生科学智能基础软硬件平台,倡议成立科学智能创新联合体
- 2022戴尔科技存储发布会 解讲PowerStore 3.0等存储新
- IBM发布全新一代 LinuxONE:3大优势助力企业构建“负责任的算力与绿色IT”,赋能客户现代化转型
- 用户邮箱的静态密码可能已被钓鱼和同一密码泄露。在没有收到安全警报的情况下,用户在适当的时间内不能更改密码。在此期间,攻击者可以随意输入帐户。启用辅助身份验证后,如果攻击者无法获取移动电话动态密码,他将无法进行身份验证。这样,除非用户的电子邮件密码和手机同时被盗,否则攻击者很难破解用户的邮箱。
- 荣获国家级实验室5项证书,戴尔关键业务利器通过计量院严苛测试
- 刘新民:向数据更靠近,向底层更深入
- 戴尔Precision 5770移动工作站 工作的好帮手
- 打开https://www.aizhan.com/输入自己想要查询的域名然后按回车键,如果做过网站都会有数据显示出来
- 戴尔服务器管理工具iDRAC、OpenManagement Enterprise、CloudIQ介绍