You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL会话变量@dep_rank不递增问题求助(LeetCode分组场景)

问题分析与解决

你的问题出在两个核心点:

  1. ORDER BY执行时机错误:MySQL中主查询的ORDER BY是在SELECT子句计算完成后才执行的。这意味着你计算@dep_rank时,数据还没按部门排序,同一个部门的员工行是分散的,导致每次判断@current_dep = department.name都不成立,@dep_rank始终被重置为1。
  2. 变量未显式初始化:@dep_rank初始值为NULL,NULL + 1的结果仍是NULL,直接导致递增逻辑失效。

修正后的SQL语句

SELECT 
    @dep_rank := IF(@current_dep = dept_name, @dep_rank + 1, 1) AS dep_rank,
    @current_dep := dept_name AS department_name,
    employee.*
FROM (
    -- 先完成关联并按部门排序,确保同部门行连续
    SELECT 
        e.*,
        d.name AS dept_name
    FROM employee e
    JOIN department d ON e.departmentid = d.id
    ORDER BY d.name
) AS sorted_emp,
-- 显式初始化会话变量,避免NULL值干扰
(SELECT @current_dep := '', @dep_rank := 0) AS init_vars

关键调整说明

  • 先排序再排名:将关联后的结果放在子查询中执行ORDER BY,确保同一个部门的所有行连续排列,这样变量判断时能正确识别同部门的行。
  • 显式初始化变量:通过(SELECT @current_dep := '', @dep_rank := 0) AS init_vars初始化变量,彻底避免NULL值导致的递增失效问题。
  • 使用显式JOIN:用显式JOIN替代原语句的隐式逗号关联,让SQL逻辑更清晰,符合现代SQL编写规范。

如果你的最终目标是找出每个部门的前3个值(比如薪资最高的3人),还需要在子查询中添加第二排序条件,并在外层过滤排名结果,示例如下:

SELECT *
FROM (
    SELECT 
        @dep_rank := IF(@current_dep = dept_name, @dep_rank + 1, 1) AS dep_rank,
        @current_dep := dept_name AS department_name,
        e.name,
        e.salary
    FROM (
        SELECT 
            e.*,
            d.name AS dept_name
        FROM employee e
        JOIN department d ON e.departmentid = d.id
        ORDER BY d.name, e.salary DESC -- 按部门分组后,薪资降序排序
    ) AS sorted_emp,
    (SELECT @current_dep := '', @dep_rank := 0) AS init_vars
) AS ranked_emp
WHERE dep_rank <= 3;

内容的提问来源于stack exchange,提问作者user3338757

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:15:13