mysql - WHERE 中的 CASE 子句

标签 mysql sql case-when

我正在做一道 Leetcode 题。 2个类似的答案已经制定出来。但我不知道为什么一个是错的,另一个是对的。以下是问题链接。目标是编写一个 SQL 查询来查找至少连续出现 3 次的所有数字。

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 := 移至case end

似乎else部分导致了一些错误,据我所知无法解释。

最佳答案

代码的第二个版本由于一个相当模糊的原因而无法工作。这部分:

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 的表达式已经具有此类动态内容。

总而言之,不建议在查询中设置变量,并且 future 版本的 MySql 可能不再支持它,如 Reference Manual 中所述。 :

Previous releases of MySQL made it possible to assign a value to a user variable in statements other than SET. This functionality is supported in MySQL 8.0 for backward compatibility but is subject to removal in a future release of MySQL.

关于mysql - WHERE 中的 CASE 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53577322/

相关文章:

mysql - 无法在mysql上分区表

java - 将 XML 数据存储到数据库中的最佳方式

sql - 查找表格中的相似之处

sql - 禁用Oracle中的所有表约束

r - R 中将函数分配给变量的 case_when() 的替代方案

c# - Mysql数据库副本供离线使用

MySQL - 使用 Join 运算符后出现重复列

php - 我将如何使用 php 和 mySQL 实现简单的站点搜索?

ruby - 我可以在 case 语句中使用 .include?() 吗? ruby

postgresql - 如何在 postgresql 查询中放置嵌套的 case-when 条件