语法
用户自定义变量用这个符号标识: @,
系统变量用这个符号标识: @@
比如:SET @name = "big_cat";
意思就是,自定义了一个叫 name 的变量,给name这个变量赋值为 big_cat
相关语法:
基本操作符 = 和 : =
“ : = ”是真正意义上的赋值操作,左边的变量设置为右边的值。
“ = ”则只在两种情况下作为赋值用,第一种就是在SET语句里面,SET var = value;
另一种是在UPDATE语句里面的那个SET;除了方面这两种情况外 "=" 则作为比较操作符使用
使用场景:
比如LeetCode上的一道题:
编写一个 SQL 查询,查找所有至少连续出现三次的数字。
+----+-----+
| Id | Num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1 |
+-----------------+
官方题解给出的答案是,连续查三次原表,三表联合,比大小,得到 >=3 次且 id 连续的值,但是一旦扩展起来就很差。
使用用户自定义变量
我们用到这个知识来完成,思想就是定义一个变量,再查询的时候统计出现的次数,那么就得到了出现次数 >=3 次的数字。
代码里面还涉及到了一个 case when的语法,我们也先复习一下:
case when
CASE
WHEN condition_1 THEN commands
WHEN condition_2 THEN commands
...
ELSE commands
END
case语句的形式如上所示,如果满足 condition 1 则执行对应后方的 commands。
直接嵌套在 select xxx中间使用。
解决题目的代码:
select distinct Num as ConsecutiveNums
from (
select Num,
case
when @prev = Num then @count := @count + 1
when (@prev := Num) is not null then @count := 1
end
as CNT
from Logs, (select @prev := null,@count := null)as t
)
as temp
where
temp.CNT >= 3
(如果本地运行sql的软件对语法比较严格可能对应的关键词大小写要更换)
下面来解释代码的运行过程:
- 最内层。
(select @prev := null,@count := null)as t
两个用户自定义变量 prev(代表前一个得到 num 的值),count 代表对应 num 的统计数量,这个查询记为 t (虽然 t 没有用到,但是 sql 规定子查询都要有别名);
- 次外层
这里是查询 logs 表和刚刚的 t ,得到每个 Num 之后,用 case 语句来控制了查询到的 CNT 值:- 把当前的 Num 赋给 prev,如果不空,那么 count 对应记为 1(遇到一个新Num的时候会执行);
- 如果prev 和当前的 Num 一样,那么 count++。(重复的情况会计数)
这一步结束得到的是每个 Num 以及对应连续出现的次数 CNT 两列值。
select Num,
case
when @prev = Num then @count := @count + 1
when (@prev := Num) is not null then @count := 1
end
as CNT
from Logs, (select @prev := null,@count := null)as t
- 最外层。从第二步得到的表中查询 distinct Num ,并且限制对应的 CNT>=3.