题目描述

(通过次数1,307 | 提交次数2,116,通过率61.77%)

表: Candidates
+-------------+------+
| Column Name | Type |
+-------------+------+
| employee_id | int  |
| experience  | enum |
| salary      | int  |
+-------------+------+
employee_id是此表的主键列。
经验是一个枚举,其中包含一个值(“高级”、“初级”)。
此表的每一行都显示候选人的id、月薪和经验。
每个候选人的工资保证是 唯一 的。

一家公司想雇佣新员工。公司的工资预算是 7 万美元。公司的招聘标准是:
继续雇佣薪水最低的高级职员,直到你不能再雇佣更多的高级职员。
用剩下的预算雇佣薪水最低的初级职员。
继续以最低的工资雇佣初级职员,直到你不能再雇佣更多的初级职员。
编写一个SQL查询,查找根据上述条件雇用职员的 ID。
按 任意顺序 返回结果表。
查询结果格式如下例所示。

示例 1:
输入:
Candidates table:
+-------------+------------+--------+
| employee_id | experience | salary |
+-------------+------------+--------+
| 1           | Junior     | 10000  |
| 9           | Junior     | 15000  |
| 2           | Senior     | 20000  |
| 11          | Senior     | 16000  |
| 13          | Senior     | 50000  |
| 4           | Junior     | 40000  |
+-------------+------------+--------+
输出: 
+-------------+
| employee_id |
+-------------+
| 11          |
| 2           |
| 1           |
| 9           |
+-------------+
解释: 
我们可以雇佣2名具有ID(11,2)的高级员工。由于预算是7万美元,他们的工资总额是3.6万美元,我们还有3.4万美元,但他们不足以雇佣ID为 13 的高级职员。
我们可以雇佣2名ID为(1,9)的初级员工。由于剩余预算为3.4万美元,他们的工资总额为2.5万美元,我们还有9000美元,但他们不足以雇佣ID为 4 的初级员工。
示例 2:

输入:
Candidates table:
+-------------+------------+--------+
| employee_id | experience | salary |
+-------------+------------+--------+
| 1           | Junior     | 25000  |
| 9           | Junior     | 10000  |
| 2           | Senior     | 85000  |
| 11          | Senior     | 80000  |
| 13          | Senior     | 90000  |
| 4           | Junior     | 30000  |
+-------------+------------+--------+
输出: 
+-------------+
| employee_id |
+-------------+
| 9           |
| 1           |
| 4           |
+-------------+
解释: 
我们不能用目前的预算雇佣任何高级员工,因为我们需要至少 80000 美元来雇佣一名高级员工。
我们可以用剩下的预算雇佣三名初级员工。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/the-number-of-seniors-and-juniors-to-join-the-company-ii
//测试数据
Create table If Not Exists Candidates (employee_id int, experience ENUM('Senior', 'Junior'), salary int);

insert into Candidates (employee_id, experience, salary) values ('1', 'Junior', '10000');
insert into Candidates (employee_id, experience, salary) values ('9', 'Junior', '15000');
insert into Candidates (employee_id, experience, salary) values ('2', 'Senior', '20000');
insert into Candidates (employee_id, experience, salary) values ('11', 'Senior', '16000');
insert into Candidates (employee_id, experience, salary) values ('13', 'Senior', '50000');
insert into Candidates (employee_id, experience, salary) values ('4', 'Junior', '40000');

解题思路

要想完成这道题,要先理解题目的要求。

首先,公司有7万美元的预算,希望从市场上招聘到级别尽量高、人数尽量多的员工。

员工的级别有Senior、Junior。而公司希望优先招聘Senior级别的员工。如果预算有剩余,再招聘尽量多的Junior级别的员工。

其次,不存在薪水相同的两个人,这样也就不存在当薪水相同时,不知道该招谁的问题。

那么,根据题目要求,需要以下几个步骤来实现:

**第一步**:按照7万美元的预算,尽量多的招聘Senior级别的员工。

具体能招聘到多少人,需要根据Senior级别的员工要求的薪水升序排序并计算累计薪水。

当累计薪水超过7万美元时,招聘截止。

这一步,可以将Senior级别的员工全部筛选出来,然后按薪水排序计算累计值即可。可以使用sum开窗函数实现:

select
      *,
      70000-sum(salary) over(order by salary) salary_bal
from Candidates
where experience = 'Senior';

**第二步**:当然,第一步招聘完成,可能还会剩余一些预算。需要使用这些预算来招聘Junior级别的员工。

计算方法跟第一步一样。不同的是,当预算使用完成时,就停止招聘。

**第三步**:将第一步、第二步招聘的员工合并返回即可。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with
tmp_senior as (
    select
      *,
        70000-sum(salary) over(order by salary) salary_bal
    from Candidates
    where experience = 'Senior'
),
tmp_junior as (
    select
        *,
        70000 - (select coalesce(sum(salary),0) from tmp_senior where salary_bal >0) - sum(salary) over(order by salary) salary_bal
    from Candidates
    where experience = 'Junior'
)
select employee_id from tmp_senior where salary_bal >0
union all
select employee_id from tmp_junior where salary_bal >0;
picture loss