使用带有临时变量的 MySQL CASE 语句,CASE 结果不正确?

Posted

技术标签:

【中文标题】使用带有临时变量的 MySQL CASE 语句,CASE 结果不正确?【英文标题】:Using MySQL CASE statement with temporary variable, and CASE result is incorrect? 【发布时间】:2021-04-01 16:26:17 【问题描述】:

我有一个示例公司 HR 数据库,其中包含员工和工作表。

employees
job_id name salary

jobs
job_id job_title

我的目标是输出一个表格,其中包含每个职位和该职位的员工人数,以及每个职位的平均工资,所以表格看起来像这样:

Job Title  Number of Employees  Average Salary  Range

这是我当前的 SQL 代码:

SELECT j.job_title AS 'Job Title', 
       COUNT(*) AS 'Number of Employees', 
       @averageSalary := ROUND(AVG(e.salary), 0) AS 'Average Salary',
       CASE 
           WHEN @averageSalary BETWEEN 0 AND 5000 THEN 'Low'
           WHEN @averageSalary BETWEEN 5001 AND 10000 THEN 'Medium'
           WHEN @averageSalary > 10001 THEN 'High'
       ELSE 'N/A' END AS 'Range'
FROM employees AS e
JOIN jobs AS j ON e.job_id = j.job_id
GROUP BY e.job_id;

我得到一个输出:

Job Title Number of Employees Salary Range
'Public Accountant', '1', '8300', 'High'
'Accounting Manager', '1', '12000', 'Medium'
'Administration Assistant', '1', '4400', 'High'
'President', '1', '24000', 'Low'

这显然是错误的,因为根据我的 CASE 声明,公共会计师的范围应该是“中”。而且我不确定为什么这是错误的。显然,我没有收到任何错误,所以我一直在寻找 CASE 结果错误,但我似乎找不到可以帮助我理解发生了什么的东西。

我做错了什么?我的语法在哪里生成不同的输出?提前谢谢!

【问题讨论】:

你不能真正使用这样的变量。 SQL 中的变量旨在用于维护批量查询之间 的状态,而不是在查询中保存临时数据。这就是派生表的用途。 (也有例外,比如连接字符串或作为ROW_NUMBER 的糟糕替代品,但我认为自从 mysql 8 推出以来,那些日子已经过去很久了)。 见meta.***.com/questions/333952/… 【参考方案1】:

使用这样的变量很棘手,因为select 子句中表达式的求值顺序是未定义的。您无法事先判断该变量是否会在 case 表达式计算之前或之后分配。

您可以重复表达式,也可以使用子查询:

select j.job_title, e.*,
        case 
            when e.average_salary between 0 and 5000 then 'low'
            when e.average_salary between 5001 and 10000 then 'medium'
            when e.average_salary > 10001 then 'high'
            else 'n/a' 
        end as salary_range
from (
    select job_id, 
        count(*) as number_of_employees, 
        round(avg(salary), 0) as average_salary
    from employees
    group by job_id
) e
inner join jobs j on j.job_id = e.job_id

【讨论】:

我个人会在外部查询而不是内部查询中使用INNER JOIN jobs - 因为当前查询依赖于 MySQL 的更宽松(即不正确)GROUP BY with-unrelated-columns 支持。

以上是关于使用带有临时变量的 MySQL CASE 语句,CASE 结果不正确?的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用带有两个变量的case / switch语句吗?

在 PHP 中使用带有 sqlsrv_query 函数的临时表不会产生任何结果

在带有 CASE 语句的 UPDATE 上使用 LAG()

我们可以在c中使用带有字符串的switch-case语句吗? [重复]

如何使用 SQL 中的 Case 语句将数据插入临时表

Oracle SQL - 带有迭代的 Case 语句