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

MySQL查询需求:找出10月、11月每月第二高薪资的员工

问题分析与修正方案

原SQL的核心问题

  1. 全局最高薪而非当月最高薪:子查询select max(sal) from employee_salary取的是全表所有记录的最高薪资,不是对应月份的最高薪,导致排除的不是当月第一高,会返回多个低于全局最高但可能高于当月第二高的员工。
  2. 关联逻辑不严谨:natural join依赖两张表的同名字段隐式关联,一旦表结构变更(比如新增同名字段)会引发意外关联,建议显式指定关联条件(如e.empid = s.empid)。
  3. 代码冗余且分组逻辑不合理:重复编写两次查询用union拼接,代码冗余;同时group by e.empid搭配max(s.sal)的逻辑无意义(若员工当月只有一条薪资记录,max不会改变结果,还可能因分组字段不完整导致数据异常)。

修正方案

方案一:使用窗口函数(MySQL 8.0+推荐)

利用DENSE_RANK()窗口函数按月份分组并对薪资排名,直接筛选排名为2的记录,逻辑清晰且高效:

SELECT 
    e.empid,
    e.firstname,
    e.lastname,
    e.dateofjoin,
    s.datesal,
    s.sal
FROM employee e
JOIN (
    SELECT 
        empid,
        datesal,
        sal,
        -- 按月份分组,薪资降序排名,并列薪资同排名
        DENSE_RANK() OVER (PARTITION BY DATE_FORMAT(datesal, '%Y-%m') ORDER BY sal DESC) AS sal_rank
    FROM employee_salary
    -- 限定查询2023年10-11月的薪资记录
    WHERE datesal BETWEEN '2023-10-01' AND '2023-11-30'
) s ON e.empid = s.empid
-- 筛选当月薪资排名第2的员工
WHERE s.sal_rank = 2;

若需要跳过并列名次(比如当月有两个最高薪,下一个直接排第3),可将DENSE_RANK()替换为RANK()。

方案二:兼容低版本MySQL(无窗口函数)

通过嵌套子查询先获取每个月的最高薪资,再找出当月中低于最高薪的最大值(即第二高),最终关联员工表:

SELECT 
    e.empid,
    e.firstname,
    e.lastname,
    e.dateofjoin,
    s.datesal,
    s.sal
FROM employee e
JOIN employee_salary s ON e.empid = s.empid
WHERE 
    -- 限定目标月份
    DATE_FORMAT(s.datesal, '%Y-%m') IN ('2023-10', '2023-11')
    -- 匹配当月第二高薪资
    AND s.sal = (
        SELECT MAX(sal)
        FROM employee_salary
        WHERE 
            DATE_FORMAT(datesal, '%Y-%m') = DATE_FORMAT(s.datesal, '%Y-%m')
            -- 排除当月最高薪
            AND sal < (
                SELECT MAX(sal)
                FROM employee_salary
                WHERE DATE_FORMAT(datesal, '%Y-%m') = DATE_FORMAT(s.datesal, '%Y-%m')
            )
    );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:22:31