MySQL CASE 语句在 Workbench 和 Angular 中返回不同的结果

Posted

技术标签:

【中文标题】MySQL CASE 语句在 Workbench 和 Angular 中返回不同的结果【英文标题】:MySQL CASE Statement Returns Different Result in Workbench and Angular 【发布时间】:2021-02-09 21:14:06 【问题描述】:

我想从我的 php API 中获得与从 mysql Workbench 调用相同的 SQL 查询时相同的结果。 我在 MySQL Workbench 中得到的结果与在使用 CASE 语句时从 PHP API 调用它时得到的结果不同。这是 SQL:

@row_number:=CASE
                            WHEN @row_number IS NULL THEN
                                1
                            WHEN @dateTime = scrm_lessons_id_lesson THEN 
                                @row_number + 0
                            WHEN @dateTime != scrm_lessons_id_lesson THEN 
                                @row_number + 1
                            END AS lesson_number,
                          
                        @dateTime:= scrm_lessons_id_lesson AS 'LessonID'

在 Workbench 中,这给了我想要的结果,即:

lesson_number   LessonID
1   17282
2   17314
2   17314
2   17314
2   17314
2   17314
2   17314
2   17314
2   17314
3   17349
3   17349
3   17349
3   17349
3   17349
3   17349
3   17349
3   17349
4   17386
4   17386
4   17386
4   17386
4   17386
5   17416
5   17416

即,具有新 LessonID 值的每一行都会增加 course_number 的值。

然而,在 PHP 中,lesson_number 的值始终为 1(因此每次都必须命中 WHEN @row_number IS NULL)。

语句是相同的,复制和粘贴,并在同一台服务器上运行。一个是从远程连接到服务器的 MySQL Workbench 调用的,另一个是从服务器上用 PHP 编写的 API 调用的。

【问题讨论】:

你运行的是哪个版本的 MySQL? 请向我们展示整个查询,而不仅仅是其中的一部分。 这可能是由于变量范围的问题 - @row_number会话变量,当从 PHP 运行时它的行为可能与您预期的不同跨度> 【参考方案1】:

用户变量在 MySQL 中很棘手 - 现在正式计划在未来版本中弃用它们。

如果您运行的是 MySL 8.0(或者您可以升级到该版本),只需使用窗口函数:dense_rank() 完全符合您的要求。

select 
    dense_rank() over(order by scrm_lessons_id_lesson) lesson_number, 
    scrm_lessons_id_lesson  lesson_id
from mytable

【讨论】:

非常感谢!那太完美了。【参考方案2】:

MySQL explicitly warns agains assigning variables and using them in the same expression:

对于其他语句,例如 SELECT,您可能会得到您期望的结果,但这不能保证。在下面的语句中,你可能会认为 MySQL 会先评估 @a,然后再进行赋值:

SELECT @a, @a:=@a+1, ...;

但是,涉及用户变量的表达式的计算顺序是未定义的。

您在不同的表达式中分配和使用变量,因此无法保证表达式的计算顺序。甚至它们在同一个查询中以相同的顺序被评估。

令人高兴的是,现在不推荐在 SELECT 语句中设置变量。在大多数情况下,您可以将逻辑替换为窗口函数。

编辑:

您的代码似乎描述了该功能:

row_number() over (partition by scrm_lessons_id_lesson order by ?) as lesson_number

? 是因为我不知道排序。它将基于您现有查询中其他地方使用的order by 子句。

【讨论】:

感谢您解释为什么它不能按预期工作。我不知道要使用哪个窗口功能。它们中的任何一个似乎都不符合我的目的。你可以说得更详细点吗?还是我试图用 SQL 做不到,我应该在 API 或客户端的代码中做吗?

以上是关于MySQL CASE 语句在 Workbench 和 Angular 中返回不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

在mysql的workbench里怎么直接改数据

mysql workbench 导出建表语句

mysql之workbench如何只导出(insert语句)数据

使用带有 INSERT 语句的 MySQL Workbench 导出数据库

如何用MySQL workbench查询数据

在mysql workbench中,通过查询语句,为啥无法修改表中的数据?需要改啥设置吗?