SQL思路解析:窗口函数该如何使用?

06-01 1379阅读

目录

🔍 Step 1:我们知道什么?

🧩 Step 2:我们要构建什么?(问题建模)

🔧 Step 3:我们如何实现它?(技术路径)

✅ 3.1 按照 turn 排序,逐个考虑

✅ 3.2 对每一个人,我们想知道“上车时的总重”

✅ 3.3 筛选哪些人可以上车

✅ 3.4 找出 turn 最大的那个(最后能上车的人)

🔄 这段 SQL 的“运行流程”是这样:

 最终 SQL 解法


表: Queue
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| person_id   | int     |
| person_name | varchar |
| weight      | int     |
| turn        | int     |
+-------------+---------+
person_id 是这个表具有唯一值的列。
该表展示了所有候车乘客的信息。
表中 person_id 和 turn 列将包含从 1 到 n 的所有数字,其中 n 是表中的行数。
turn 决定了候车乘客上巴士的顺序,其中 turn=1 表示第一个上巴士,turn=n 表示最后一个上巴士。
weight 表示候车乘客的体重,以千克为单位。

有一队乘客在等着上巴士。然而,巴士有1000  千克 的重量限制,所以其中一部分乘客可能无法上巴士。

编写解决方案找出 最后一个 上巴士且不超过重量限制的乘客,并报告 person_name 。题目测试用例确保顺位第一的人可以上巴士且不会超重。

返回结果格式如下所示。

示例 1:
输入:
Queue 表
+-----------+-------------+--------+------+
| person_id | person_name | weight | turn |
+-----------+-------------+--------+------+
| 5         | Alice       | 250    | 1    |
| 4         | Bob         | 175    | 5    |
| 3         | Alex        | 350    | 2    |
| 6         | John Cena   | 400    | 3    |
| 1         | Winston     | 500    | 6    |
| 2         | Marie       | 200    | 4    |
+-----------+-------------+--------+------+
输出:
+-------------+
| person_name |
+-------------+
| John Cena   |
+-------------+
解释:
为了简化,Queue 表按 turn 列由小到大排序。
+------+----+-----------+--------+--------------+
| Turn | ID | Name      | Weight | Total Weight |
+------+----+-----------+--------+--------------+
| 1    | 5  | Alice     | 250    | 250          |
| 2    | 3  | Alex      | 350    | 600          |
| 3    | 6  | John Cena | 400    | 1000         | (最后一个上巴士)
| 4    | 2  | Marie     | 200    | 1200         | (无法上巴士)
| 5    | 4  | Bob       | 175    | ___          |
| 6    | 1  | Winston   | 500    | ___          |
+------+----+-----------+--------+--------------+

来源:Leecode


🔍 Step 1:我们知道什么?

  • 所有人都有唯一的上车顺序(turn)。

    SQL思路解析:窗口函数该如何使用?
    (图片来源网络,侵删)
  • 上车顺序已知,即我们可以将人按 turn ASC 排序。

  • 每个人有体重。巴士的总承重上限是 1000kg。

    SQL思路解析:窗口函数该如何使用?
    (图片来源网络,侵删)
  • 从第一个人开始累加,如果加上某个人会超过 1000kg,则此人不能上,前面的人都上了。

    🧩 Step 2:我们要构建什么?(问题建模)

    我们想要解决的是:

    SQL思路解析:窗口函数该如何使用?
    (图片来源网络,侵删)

    在 turn 排序下,找出满足 累积体重 ≤ 1000kg 的 最大 turn 的人。

    这个问题实质上是个“顺序累加 + 截断”的问题。

    🧠 核心思想:

    1. 从第一个人开始(turn=1),累计体重;

    2. 当某人加进去刚好等于或不超过1000,就暂时保留;

    3. 一旦某人加进去会导致总重超过1000,我们就停止,返回上一个能上车的人。

    🔧 Step 3:我们如何实现它?(技术路径)

    接下来我们从本质逐步推导 SQL 解法。

    ✅ 3.1 按照 turn 排序,逐个考虑

    首先我们知道人要按 turn 排序:

    SELECT * FROM Queue ORDER BY turn;
    

    ✅ 3.2 对每一个人,我们想知道“上车时的总重”

    这时我们有了一个自然的问题:

    在某个人 turn 时,上车总重是多少?

    这就引出了窗口函数的使用 —— 我们希望每一行“看到前面的人的体重总和”。

    🎯 这里 SUM(...) OVER (...) 的意思是:

    对当前人以及比他更早上车的人的体重累加。

    这样我们就知道了:每个人上车时的总重量。

    SELECT 
        person_name,
        turn,
        weight,
        SUM(weight) OVER (ORDER BY turn) AS cumulative_weight
    FROM Queue;
    

    这一行在做的是: 

     每个乘客“看到自己和自己前面人”所有体重的累加。

    补充:为什么不能用普通 GROUP BY 或子查询替代?

    很多同学会想:我用一个变量手动累加不就可以了?

    但在 SQL 中,每行是独立执行的,你不能在一行里“记住上一行”的累计除非你用:

    • 窗口函数 ✅

    • 临时变量(不推荐,且部分 SQL 不支持)

      ✅ 3.3 筛选哪些人可以上车

      下一步逻辑就是:

      只保留 cumulative_weight

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码