我在做一个leetcode问题。得出了2个类似的答案。但是我不知道为什么一个是错误的而另一个是正确的。以下是问题链接。目标是编写一个SQL查询来查找至少连续出现三次的所有数字。
https://leetcode.com/problems/consecutive-numbers/
表看起来像
| Id | Num |
|----|-----|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
正确的版本:
select distinct Num as ConsecutiveNums
from Logs, (select @prev := -1, @count := 0) as Init
where (@count := case when @prev = (@prev := Num) then @count + 1 else 1 end) >= 3
输出:
| ConsecutiveNums |
|-----------------|
| 1 |
版本错误:
select distinct Num as ConsecutiveNums
from Logs, (select @prev := -1, @count := 0) as Init
where (case when @prev = (@prev := Num) then @count := @count + 1 else @count := 1 end) >= 3
输出:
| ConsecutiveNums |
|-----------------|
| 1 |
| 2 |
唯一的区别是@count:=被移至案例结尾。
似乎 else 部分引起了一些错误,据我所知无法解释。
答案 0 :(得分:1)
第二个版本的代码由于相当晦涩的原因而无法正常工作。这部分:
else @count := 1
...具有一个没有动态成分的表达式。 MySql以不再次执行该分配的方式来优化其执行计划,而是仅返回@count
的当前值。这是因为MySql变量实际上并不是设计为在查询执行期间 进行修改的。当您仍然决定使用该副作用时,必须注意这种“优化”行为。
您可以尝试迫使MySql每次 进行分配。这可以通过在分配的表达式中包含变量或字段引用来完成。例如,您可以使用:= if(@count, 1, 1)
而不是:= 1
。结果是相同的(总是1),但是现在每次遇到它时,它都会被重新评估和分配:
where (case when @prev = (@prev := Num)
then @count := @count + 1
else @count := if(@count, 1, 1)
end) >= 3
您可以想到其他替代表达式,例如:= 1+Num*0
,只要有对某些变量/字段的引用,它就能解决问题。
查看您提供的查询的第一个版本,您会发现分配给@count
的表达式已经具有这种动态内容。
总而言之,不建议在查询中设置变量,如Reference Manual所述,MySql的未来版本可能不再支持该变量:
以前的MySQL版本使得可以在
SET
以外的语句中为用户变量分配值。 MySQL 8.0支持此功能以实现向后兼容,但是在将来的MySQL版本中可能会删除该功能。
答案 1 :(得分:0)
因为您没有将“> = 3”与count进行比较。我们正尝试对这三个连续数字进行测试。在错误的版本中,不确定为什么会有“ =-10”。 “错误”版本的更正版本是:
SELECT num AS ConsecutiveNums
FROM logs,
(SELECT @prev := -1,
@count := 0) AS Init
WHERE ( @count := CASE
WHEN @prev = ( @prev := num ) THEN @count := @count + 1
ELSE @count
end ) >= 3
我还添加了一个不同的测试用例,以确保:
{"headers": {"Logs": ["Id", "Num"]}, "rows": {"Logs": [[1, 2], [2, 1], [3, 1], [4, 6], [5, 2], [6, 2], [7, 2]]}}
不更改测试用例的默认值将给出“ 1”,该测试用例应返回“ 2”
答案 2 :(得分:0)
DECLARE @max_id INTEGER
SET @max_id = (SELECT COUNT(*) FROM seat)
SELECT CASE WHEN id < @max_id THEN case when id%2<>0 then id+1 when id%2=0 then id-1 end
WHEN id = @max_id THEN case when id%2=0 then id-1 else id
END id
,student
FROM seat
ORDER BY id
SET @max_id = (SELECT max(id) FROM Seat)
选择
案件
当 id!=@max_id THEN
案件
当 id%2!=0 那么 id+1
当 id%2=0 则 id-1
结尾
当 id= @max_id THEN
案例
当 id%2=0 则 id-1
当 id%2!=0 THEN id
结尾
结束编号
, 学生
从座位
按 id 排序`
答案 3 :(得分:-1)
如果连续意味着id递增“ 1”(如示例数据中所示),则不需要变量-甚至不需要变量:
select t1.num
from t t1 join
t t2
on t2.id = t1.id + 1 and t2.num = t1.num join
t t3
on t3.id = t1.id + 2 and t3.num = t1.num;
如果您有三个以上的连续值或一个与多行匹配的num
,那么您可能想要select distinct num
。