问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

LeetCode 579:查询员工的累计薪水

创作时间:
作者:
@小白创作中心

LeetCode 579:查询员工的累计薪水

引用
CSDN
1.
https://m.blog.csdn.net/qq_58114907/article/details/144492428

1. 力扣链接

  1. 查询员工的累计薪水 - 力扣(LeetCode)

2. 题目

表:
Employee

+-------------+------+
| Column Name | Type |
+-------------+------+
| id | int |
| month | int |
| salary | int |
+-------------+------+
(id, month) 是该表的主键(具有唯一值的列的组合)。
表中的每一行表示 2020 年期间员工一个月的工资。

编写一个解决方案,在一个统一的表中计算出每个员工的 累计工资汇总
员工的 累计工资汇总 可以计算如下:

  • 对于该员工工作的每个月,将 该月前两个月 的工资 起来。这是他们当月的 3 个月总工资 。如果员工在前几个月没有为公司工作,那么他们在前几个月的有效工资为
    0
  • 不要 在摘要中包括员工 最近一个月 的 3 个月总工资和。
  • 不要 包括雇员 没有工作 的任何一个月的 3 个月总工资和。
    返回按
    id
    升序排序 的结果表。如果
    id
    相等,请按
    month
    降序排序
    结果格式如下所示。

示例 1

**输入:**
Employee table:
+----+-------+--------+
| id | month | salary |
+----+-------+--------+
| 1 | 1 | 20 |
| 2 | 1 | 20 |
| 1 | 2 | 30 |
| 2 | 2 | 30 |
| 3 | 2 | 40 |
| 1 | 3 | 40 |
| 3 | 3 | 60 |
| 1 | 4 | 60 |
| 3 | 4 | 70 |
| 1 | 7 | 90 |
| 1 | 8 | 90 |
+----+-------+--------+
**输出:**
+----+-------+--------+
| id | month | Salary |
+----+-------+--------+
| 1 | 7 | 90 |
| 1 | 4 | 130 |
| 1 | 3 | 90 |
| 1 | 2 | 50 |
| 1 | 1 | 20 |
| 2 | 1 | 20 |
| 3 | 3 | 100 |
| 3 | 2 | 40 |
+----+-------+--------+
**解释:**
员工 “1” 有 5 条工资记录,不包括最近一个月的 “8”:
- 第 '7' 个月为 90。
- 第 '4' 个月为 60。
- 第 '3' 个月是 40。
- 第 '2' 个月为 30。
- 第 '1' 个月为 20。
因此,该员工的累计工资汇总为:
+----+-------+--------+
| id | month | salary |
+----+-------+--------+
| 1 | 7 | 90 | (90 + 0 + 0)
| 1 | 4 | 130 | (60 + 40 + 30)
| 1 | 3 | 90 | (40 + 30 + 20)
| 1 | 2 | 50 | (30 + 20 + 0)
| 1 | 1 | 20 | (20 + 0 + 0)
+----+-------+--------+
请注意,'7' 月的 3 个月的总和是 90,因为他们没有在 '6' 月或 '5' 月工作。
员工 '2' 只有一个工资记录('1' 月),不包括最近的 '2' 月。
+----+-------+--------+
| id | month | salary |
+----+-------+--------+
| 2 | 1 | 20 | (20 + 0 + 0)
+----+-------+--------+
员工 '3' 有两个工资记录,不包括最近一个月的 '4' 月:
- 第 '3' 个月为 60 。
- 第 '2' 个月是 40。
因此,该员工的累计工资汇总为:
+----+-------+--------+
| id | month | salary |
+----+-------+--------+
| 3 | 3 | 100 | (60 + 40 + 0)
| 3 | 2 | 40 | (40 + 0 + 0)
+----+-------+--------+
  
-- 建表语句
Create table If Not Exists Employee (id int, month int, salary int);
Truncate table Employee;
insert into Employee (id, month, salary) values ('1', '1', '20');
insert into Employee (id, month, salary) values ('2', '1', '20');
insert into Employee (id, month, salary) values ('1', '2', '30');
insert into Employee (id, month, salary) values ('2', '2', '30');
insert into Employee (id, month, salary) values ('3', '2', '40');
insert into Employee (id, month, salary) values ('1', '3', '40');
insert into Employee (id, month, salary) values ('3', '3', '60');
insert into Employee (id, month, salary) values ('1', '4', '60');
insert into Employee (id, month, salary) values ('3', '4', '70');
insert into Employee (id, month, salary) values ('1', '7', '90');
insert into Employee (id, month, salary) values ('1', '8', '90');  

3. 分析

  1. 理解数据结构:首先,我们需要理解
    Employee
    表的结构,它包含三个字段:
    id
    (员工ID),
    month
    (月份),和
    salary
    (工资)。
  2. 确定累计工资计算规则:累计工资是当前月工资加上前两个月的工资。如果员工在前几个月没有工作,那么前几个月的工资视为0。
  3. 排除最近一个月:在计算累计工资时,需要排除最近一个月的数据。
  4. 排除未工作月份:如果员工在某个月没有工作记录,那么这个月不应该被包括在累计工资的计算中,这里就要确定开窗范围要用range对值就是范围界定,而不是通过rows进行确定。
  5. 排序要求:结果需要按照员工ID升序排序,如果员工ID相同,则按照月份降序排序。
  6. 处理边界情况:对于每个员工的前两个月,由于没有前一个月或两个月的数据,这些月份的工资应该视为0。

4. 代码实现

  
with tmp as (
    select
        id,
        month,
        -- 计算最近月份
        max(month) over (partition by id) max_month,
        -- 计算前两月到当前月的工资和
        sum(salary) over (partition by id order by month range between 2 preceding and current row) salary
    from EMPLOYEE  order by id,month desc
 )
 select
    id,
    month,
    salary
from tmp
where month < max_month;  

5. 代码验证

6. 总结

  • 窗口函数:用于对数据进行分组内计算,不改变原始数据集的行数。
  • 分区:通过
    PARTITION BY
    子句,将数据集划分为多个分区,每个分区独立进行窗口函数计算。
  • 排序
    ORDER BY
    子句在窗口函数中定义了计算的顺序,确保数据按期望顺序处理。
  • 范围聚合
    RANGE
    子句指定了窗口函数的计算范围,允许跨行计算,如计算前两月到当前月的工资和。
  • 累计计算:通过窗口函数实现累计工资的计算,适用于需要考虑之前数据的场景。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号