跳转至

3580. 寻找持续进步的员工

题目描述

表:employees

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| employee_id | int     |
| name        | varchar |
+-------------+---------+
employee_id 是这张表的唯一主键。
每一行包含一名员工的信息。

表:performance_reviews

+-------------+------+
| Column Name | Type |
+-------------+------+
| review_id   | int  |
| employee_id | int  |
| review_date | date |
| rating      | int  |
+-------------+------+
review_id 是这张表的唯一主键。
每一行表示一名员工的绩效评估。评分在 1-5 的范围内,5分代表优秀,1分代表较差。

编写一个解决方案,以找到在过去三次评估中持续提高绩效的员工。

  • 员工 至少需要 3 次评估 才能被考虑
  • 员工过去的 3 次评估,评分必须 严格递增(每次评价都比上一次好)
  • 根据 review_date 为每位员工分析最近的 3 次评估
  • 进步分数 为最后 3 次评估中最后一次评分与最早一次评分之间的差值

返回结果表以 进步分数 降序 排序,然后以 名字 升序 排序。

结果格式如下所示。

 

示例:

输入:

employees 表:

+-------------+----------------+
| employee_id | name           |
+-------------+----------------+
| 1           | Alice Johnson  |
| 2           | Bob Smith      |
| 3           | Carol Davis    |
| 4           | David Wilson   |
| 5           | Emma Brown     |
+-------------+----------------+

performance_reviews 表:

+-----------+-------------+-------------+--------+
| review_id | employee_id | review_date | rating |
+-----------+-------------+-------------+--------+
| 1         | 1           | 2023-01-15  | 2      |
| 2         | 1           | 2023-04-15  | 3      |
| 3         | 1           | 2023-07-15  | 4      |
| 4         | 1           | 2023-10-15  | 5      |
| 5         | 2           | 2023-02-01  | 3      |
| 6         | 2           | 2023-05-01  | 2      |
| 7         | 2           | 2023-08-01  | 4      |
| 8         | 2           | 2023-11-01  | 5      |
| 9         | 3           | 2023-03-10  | 1      |
| 10        | 3           | 2023-06-10  | 2      |
| 11        | 3           | 2023-09-10  | 3      |
| 12        | 3           | 2023-12-10  | 4      |
| 13        | 4           | 2023-01-20  | 4      |
| 14        | 4           | 2023-04-20  | 4      |
| 15        | 4           | 2023-07-20  | 4      |
| 16        | 5           | 2023-02-15  | 3      |
| 17        | 5           | 2023-05-15  | 2      |
+-----------+-------------+-------------+--------+

输出:

+-------------+----------------+-------------------+
| employee_id | name           | improvement_score |
+-------------+----------------+-------------------+
| 2           | Bob Smith      | 3                 |
| 1           | Alice Johnson  | 2                 |
| 3           | Carol Davis    | 2                 |
+-------------+----------------+-------------------+

解释:

  • Alice Johnson (employee_id = 1):
    • 有 4 次评估,分数:2, 3, 4, 5
    • 最后 3 次评估(按日期):2023-04-15 (3), 2023-07-15 (4), 2023-10-15 (5)
    • 评分严格递增:3 → 4 → 5
    • 进步分数:5 - 3 = 2
  • Carol Davis (employee_id = 3):
    • 有 4 次评估,分数:1, 2, 3, 4
    • 最后 3 次评估(按日期):2023-06-10 (2),2023-09-10 (3),2023-12-10 (4)
    • 评分严格递增:2 → 3 → 4
    • 进步分数:4 - 2 = 2
  • Bob Smith (employee_id = 2):
    • 有 4 次评估,分数:3,2,4,5
    • 最后 3 次评估(按日期):2023-05-01 (2),2023-08-01 (4),2023-11-01 (5)
    • 评分严格递增:2 → 4 → 5
    • 进步分数:5 - 2 = 3
  • 未包含的员工:
    • David Wilson (employee_id = 4):之前 3 次评估都是 4 分(没有进步)
    • Emma Brown (employee_id = 5):只有 2 次评估(需要至少 3 次)

输出表以 improvement_score 降序排序,然后以 name 升序排序。

解法

方法一:使用窗口函数和聚合函数

我们首先将每个员工的最近三次绩效评估记录提取出来,并计算出每次评估的评分与前一次评估的评分之差。接着,我们筛选出那些评分严格递增的员工,并计算他们的改进分数(即最后一次评分减去第一次评分)。最后,我们按照改进分数降序排列,并按姓名升序排列。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
WITH
    recent AS (
        SELECT
            employee_id,
            review_date,
            ROW_NUMBER() OVER (
                PARTITION BY employee_id
                ORDER BY review_date DESC
            ) AS rn,
            (
                LAG(rating) OVER (
                    PARTITION BY employee_id
                    ORDER BY review_date DESC
                ) - rating
            ) AS delta
        FROM performance_reviews
    )
SELECT
    employee_id,
    name,
    SUM(delta) AS improvement_score
FROM
    recent
    JOIN employees USING (employee_id)
WHERE rn > 1 AND rn <= 3
GROUP BY 1
HAVING COUNT(*) = 2 AND MIN(delta) > 0
ORDER BY 3 DESC, 2;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import pandas as pd


def find_consistently_improving_employees(
    employees: pd.DataFrame, performance_reviews: pd.DataFrame
) -> pd.DataFrame:
    performance_reviews = performance_reviews.sort_values(
        ["employee_id", "review_date"], ascending=[True, False]
    )
    performance_reviews["rn"] = (
        performance_reviews.groupby("employee_id").cumcount() + 1
    )
    performance_reviews["lag_rating"] = performance_reviews.groupby("employee_id")[
        "rating"
    ].shift(1)
    performance_reviews["delta"] = (
        performance_reviews["lag_rating"] - performance_reviews["rating"]
    )
    recent = performance_reviews[
        (performance_reviews["rn"] > 1) & (performance_reviews["rn"] <= 3)
    ]
    improvement = (
        recent.groupby("employee_id")
        .agg(
            improvement_score=("delta", "sum"),
            count=("delta", "count"),
            min_delta=("delta", "min"),
        )
        .reset_index()
    )
    improvement = improvement[
        (improvement["count"] == 2) & (improvement["min_delta"] > 0)
    ]
    result = improvement.merge(employees[["employee_id", "name"]], on="employee_id")
    result = result.sort_values(
        by=["improvement_score", "name"], ascending=[False, True]
    )
    return result[["employee_id", "name", "improvement_score"]]

评论