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

PostgreSQL查询需求:获取每位员工的最新晋升记录

解决方案:查询员工及最新晋升记录

问题背景

我们有三张业务表:employee(员工信息)、rank(职级信息)、promotion(晋升记录),需要实现:查询employee的所有记录,同时关联每位员工**最新(最大晋升日期)**的晋升记录;对于没有晋升记录的员工,对应晋升字段显示NULL。

给定的表结构与测试数据如下:

create table employee(id int, name varchar(50), fname varchar(50)); 
create table rank (id int, name varchar(50)); 
create table promotion(
    id int, 
    dt date, 
    from_rank_id int, 
    to_rank_id int, 
    employee_id int, 
    constraint fk_pro_emp foreign key(employee_id) references employee(id),
    constraint fk_pro_rank_f foreign key(from_rank_id) references rank(id),
    constraint fk_pro_rank_t foreign key(to_rank_id) references rank(id)
); 

insert into employee values(1, 'John', 'Roy'), (2, 'Kane', 'Williamson'), (3, 'Yasin', 'Khan'), (4, 'Dwayne', 'Brain'); 
insert into rank values(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E'); 

-- 同一员工多条晋升记录
insert into promotion values(1, '2010-01-01', 1, 2, 1), (2, '2015-01-01', 2, 3, 1); 
-- 第二位员工三次晋升
insert into promotion values(4, '2011-11-23', 1, 2, 2), (5, '2012-04-05', 2, 3, 2), (6, '2013-12-30', 3, 4, 2); 
-- 第三位员工一次晋升
insert into promotion values(7, '2015-10-21', 3, 4, 3); 
-- 第四位员工无晋升记录

期望输出格式:

EMP_ID Name      Father_Name Pro_Date   From_Rank To_Rank
1      John      Roy         2015-01-01 B         C
2      Kane      Williamson  2013-12-30 C         D
3      Yasin     Khan        2015-10-21 C         D
4      Dwayne    Brain       <Null>     <Null>    <Null>

方案1:使用窗口函数(推荐,简洁高效)

利用ROW_NUMBER()窗口函数,按员工ID分组,对每组的晋升记录按日期降序排序,取排序后第一条(即最新晋升),再关联员工表和职级表:

SELECT
    e.id AS EMP_ID,
    e.name AS Name,
    e.fname AS Father_Name,
    p.dt AS Pro_Date,
    r_from.name AS From_Rank,
    r_to.name AS To_Rank
FROM employee e
LEFT JOIN (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY dt DESC) AS rn
    FROM promotion
) p ON e.id = p.employee_id AND p.rn = 1
LEFT JOIN rank r_from ON p.from_rank_id = r_from.id
LEFT JOIN rank r_to ON p.to_rank_id = r_to.id
ORDER BY e.id;

优势:逻辑直观,代码简洁,在MySQL 8+、PostgreSQL、SQL Server等现代数据库中都支持,执行效率较高。


方案2:子查询获取最大晋升日期(兼容性强)

先通过子查询找出每个员工的最大晋升日期,再关联晋升表拿到对应记录,最后关联职级表:

SELECT
    e.id AS EMP_ID,
    e.name AS Name,
    e.fname AS Father_Name,
    p.dt AS Pro_Date,
    r_from.name AS From_Rank,
    r_to.name AS To_Rank
FROM employee e
LEFT JOIN (
    SELECT employee_id, MAX(dt) AS max_dt
    FROM promotion
    GROUP BY employee_id
) p_max ON e.id = p_max.employee_id
LEFT JOIN promotion p ON p.employee_id = p_max.employee_id AND p.dt = p_max.max_dt
LEFT JOIN rank r_from ON p.from_rank_id = r_from.id
LEFT JOIN rank r_to ON p.to_rank_id = r_to.id
ORDER BY e.id;

优势:兼容所有支持基本SQL语法的数据库,包括MySQL 5.x等旧版本。


关键说明

两种方案都使用LEFT JOIN保证无晋升记录的员工也会被纳入结果集,对应晋升字段自动显示NULL,完全匹配需求。

内容的提问来源于stack exchange,提问作者Abdul Raheem Ghani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:35:25