题目描述

(通过次数9,066 | 提交次数12,303,通过率73.69%)

表: Queue
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| person_id   | int     |
| person_name | varchar |
| weight      | int     |
| turn        | int     |
+-------------+---------+
person_id 是这个表的主键。
该表展示了所有等待电梯的人的信息。
表中 person_id 和 turn 列将包含从 1 到 n 的所有数字,其中 n 是表中的行数。

有一群人在等着上电梯。然而,电梯有1000公斤的重量限制,所以可能会有一些人不能上。

写一条 SQL 查询语句查找 最后一个 能进入电梯且不超过重量限制的 person_name 。题目确保队列中第一位的人可以进入电梯,不会超重。
查询结果如下所示。
示例 1:
输入:
Queue 表
+-----------+-------------------+--------+------+
| person_id | person_name       | weight | turn |
+-----------+-------------------+--------+------+
| 5         | George Washington | 250    | 1    |
| 3         | John Adams        | 350    | 2    |
| 6         | Thomas Jefferson  | 400    | 3    |
| 2         | Will Johnliams    | 200    | 4    |
| 4         | Thomas Jefferson  | 175    | 5    |
| 1         | James Elephant    | 500    | 6    |
+-----------+-------------------+--------+------+
输出:
+-------------------+
| person_name       |
+-------------------+
| Thomas Jefferson  |
+-------------------+
解释:
为了简化,Queue 表按 turn 列由小到大排序。
上例中 George Washington(id 5), John Adams(id 3) 和 Thomas Jefferson(id 6) 将可以进入电梯,因为他们的体重和为 250 + 350 + 400 = 1000。
Thomas Jefferson(id 6) 是最后一个体重合适并进入电梯的人。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/last-person-to-fit-in-the-bus
//测试数据
Create table If Not Exists Queue (person_id int, person_name varchar(30), weight int, turn int);

insert into Queue (person_id, person_name, weight, turn) values ('5', 'Alice', '250', '1');
insert into Queue (person_id, person_name, weight, turn) values ('4', 'Bob', '175', '5');
insert into Queue (person_id, person_name, weight, turn) values ('3', 'Alex', '350', '2');
insert into Queue (person_id, person_name, weight, turn) values ('6', 'John Cena', '400', '3');
insert into Queue (person_id, person_name, weight, turn) values ('1', 'Winston', '500', '6');
insert into Queue (person_id, person_name, weight, turn) values ('2', 'Marie', '200', '4');

解题思路

这是一个典型的求累计值的题目。
一般情况下,使用sum开窗函数进行累计会非常的方便。语法如下:


sum(累计字段名) over(partition by 开窗字段 order by 排序字段)

累计字段名:指定按哪个字段进行累计计算;
开窗字段:指定按哪(几)个字段进行分组开窗;该子句可以省略,表示将全表数据放在一组进行开窗。
排序字段:指定按哪(几)个字段的排序顺序进行依次累计;
回到本题目,要求计算按顺序上车的乘客,最后一个可乘车的乘客姓名。
首先,因为电梯的容量是按载重计算的,因此,需要对乘客的体重进行累计计算;
然后,因为表中只有一辆车的数据,所以可以对全表开窗。
最后,因为乘客是按给定的顺序上的电梯,因此,可以按上电梯的顺序进行排序。
这样可以计算出每一个上电梯的人,截止到自己,累计的体重有多重。剔除那些超过电梯载重的乘客,再返回累计体重最大的那个人即可。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select
    person_name
from (
    select
        person_name,
        sum(weight) over(order by turn) sum_weight
    from Queue
)a
where sum_weight <= 1000
order by sum_weight desc
limit 1;
picture loss