【LeetCode-SQL】1988. 找出每所学校的最低分数要求

本文介绍了如何使用SQL查询每所学校的最低分数要求,基于LeetCode的题目,通过left join和窗口函数两种方法进行解答,并提供了详细的解题思路和代码示例。

一、题目

表: Schools

+-------------+------+
| Column Name | Type |
+-------------+------+
| school_id   | int  |
| capacity    | int  |
+-------------+------+
school_id 是该表的主键。
此表包含了一些学校的容纳能力。容纳能力指的是学校能够接纳学生的最大数量。

表: Exam

+---------------+------+
| Column Name   | Type |
+---------------+------+
| score         | int  |
| student_count | int  |
+---------------+------+
score 是该表的主键。
表中每一行表示有 student_count 名学生在考试中至少获得了 score 分。
表中的数据在逻辑上是正确的,即记录了高score的行相比记录了低score的行拥有相同或更少的student_count。

也就是说,对于表中的i行与j行,如果scorei > scorej,那么student_counti <= student_countj
每年,学校会公布学生申请所需的最低分数要求。学校根据所有学生的考试成绩来决定其最低分数要求。

  1. 学校希望确保即使每一个满足分数要求的学生都申请该学校,学校也有足够的能力接纳每一个学生。
  2. 学校也希望尽可能多的学生能申请该学校。
  3. 学校必须使用在 Exam 表中的 score 来作为最低分数要求。

编写一个SQL查询来查询每所学校的最低分数要求。如果同时有多个score值满足上述要求,则选择其中最小的一个。如果数据不足以决定最低分数要求,那么输出 -1。

返回的结果表可以按任意顺序排序。

查询结果格式如下例所示:

示例:

输入:
Schools 表:
+-----------+----------+
| school_id | capacity |
+-----------+----------+
| 11        | 151      |
| 5         | 48       |
| 9         | 9        |
| 10        | 99       |
+-----------+----------+
Exam 表:
+-------+---------------+
| score | student_count |
+-------+---------------+
| 975   | 10            |
| 966   | 60            |
| 844   | 76            |
| 749   | 76            |
| 744   | 100           |
+-------+---------------+
输出:
+-----------+-------+
| school_id | score |
+-----------+-------+
| 5         | 975   |
| 9         | -1    |
| 10        | 749   |
| 11        | 744   |
+-----------+-------+
解释: 
- School 5:学校的容纳能力为 48 。选择 975 作为最低分数要求,因为学校最多会收到 10 份申请,这在学校的容纳能力以内。
- School 10:学校的容纳能力为 99 。可以选择 844749 作为最低分数要求,因为学校最多会收到 76 份申请,这在学校的容纳能力以内。又因为 749 是所有可选项中最小的,因此我们选择 749- School 11:学校的容纳能力为 151 。选择 744 作为最低分数要求,因为学校最多会收到 100 份申请,这在学校的容纳能力以内。
- School 9:给出的数据不足以确定最低分数要求。如果选择 975 作为最低分数要求,学校可能会收到 10 份申请,然而学校的容纳能力只有 9 。我们没有关于更高分数的信息,因此我们返回 -1

二、解决

1、left join

思路:

S1:两表通过容量与人数关联。
S2:再判断筛选扣除。

    select
        t1.*
        , t2.*
    from schools as t1 
    left join exam as t2 
    on t1.capacity >= t2.student_count

# {"headers": ["school_id", "capacity", "score", "student_count"], "values": [
#     [11, 151, 744, 100], 
#     [11, 151, 749, 76], 
#     [11, 151, 844, 76], 
#     [11, 151, 966, 60], 
#     [11, 151, 975, 10], 
#     [5, 48, 975, 10], 
#     [9, 9, null, null], 
#     [10, 99, 749, 76], 
#     [10, 99, 844, 76], 
#     [10, 99, 966, 60], 
#     [10, 99, 975, 10]
# ]}

代码:

select
    school_id
    , coalesce(min(score), -1) as score  # 或: ifnull(min(score), -1) as score
from (
    select
        t1.school_id
        , t2.score
    from schools as t1 
    left join exam as t2 
    on t1.capacity >= t2.student_count
) as t3
group by school_id
order by score desc;

补充: coalesce() 函数

select coalesce(success_cnt, 1) from tableA

# 当success_cnt 为null值的时候,将返回1,否则将返回success_cnt的真实值。

2、窗口函数

思路: 略。
代码:

select 
    school_id
    , score 
from (
    select 
        *
        , rank() over (partition by school_id order by student_count desc, score asc) as rnk
    from (
        select 
            school_id
            , capacity
            , coalesce(score,-1) as score
            , coalesce(student_count,-1) as student_count
        from Schools t1
        left join Exam t2
        on t1.capacity >= t2.student_count
    ) t3
) t4
where rnk = 1;

三、参考

1、MySQL, 两种解法,简洁高效
2、分步骤解决,简单易懂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值