使用带有临时变量的 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 结果不正确?的主要内容,如果未能解决你的问题,请参考以下文章
在 PHP 中使用带有 sqlsrv_query 函数的临时表不会产生任何结果