力扣-Mysql-1811 - 寻找面试候选人(中等)

一、题目来源

1811. 寻找面试候选人 - 力扣(LeetCode)

二、数据表结构

表: Contests

复制代码
+--------------+------+
| Column Name  | Type |
+--------------+------+
| contest_id   | int  |
| gold_medal   | int  |
| silver_medal | int  |
| bronze_medal | int  |
+--------------+------+
contest_id 是该表的主键.
该表包含LeetCode竞赛的ID和该场比赛中金牌、银牌、铜牌的用户id。
可以保证,所有连续的比赛都有连续的ID,没有ID被跳过。

表: Users

复制代码
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| user_id     | int     |
| mail        | varchar |
| name        | varchar |
+-------------+---------+
user_id 是该表的主键.
该表包含用户信息。

三、需求

编写 SQL 语句来返回 所有面试候选人 的姓名 name 和邮件 mail 。当用户满足以下两个要求中的 任意一条 ,其成为 面试候选人:

  • 该用户在 连续三场及更多 比赛中赢得 任意 奖牌。
  • 该用户在 三场及更多不同的 比赛中赢得 金牌(这些比赛可以不是连续的)

可以以 任何顺序 返回结果。

四、示例数据

复制代码
输入:
Contests表:
+------------+------------+--------------+--------------+
| contest_id | gold_medal | silver_medal | bronze_medal |
+------------+------------+--------------+--------------+
| 190        | 1          | 5            | 2            |
| 191        | 2          | 3            | 5            |
| 192        | 5          | 2            | 3            |
| 193        | 1          | 3            | 5            |
| 194        | 4          | 5            | 2            |
| 195        | 4          | 2            | 1            |
| 196        | 1          | 5            | 2            |
+------------+------------+--------------+--------------+
Users表:
+---------+--------------------+-------+
| user_id | mail               | name  |
+---------+--------------------+-------+
| 1       | sarah@leetcode.com | Sarah |
| 2       | bob@leetcode.com   | Bob   |
| 3       | alice@leetcode.com | Alice |
| 4       | hercy@leetcode.com | Hercy |
| 5       | quarz@leetcode.com | Quarz |
+---------+--------------------+-------+
输出:
+-------+--------------------+
| name  | mail               |
+-------+--------------------+
| Sarah | sarah@leetcode.com |
| Bob   | bob@leetcode.com   |
| Alice | alice@leetcode.com |
| Quarz | quarz@leetcode.com |
+-------+--------------------+
解释:
Sarah 赢得了3块金牌 (190, 193, and 196),所以我们将她列入结果表。
Bob在连续3场竞赛中赢得了奖牌(190, 191, and 192), 所以我们将他列入结果表。
    - 注意他在另外的连续3场竞赛中也赢得了奖牌(194, 195, and 196).
Alice在连续3场竞赛中赢得了奖牌 (191, 192, and 193), 所以我们将她列入结果表。
Quarz在连续5场竞赛中赢得了奖牌(190, 191, 192, 193, and 194), 所以我们将他列入结果表。

五、分析

1.文字分析

本题需求为寻找面试候选人:

第一步:首先寻找三场及更多获得金牌的人,将两表关联,关联条件为u.user_id = c.gold_medal,然后使用count()函数获取用户获取金牌次数,取次数大于等于3的用户;

第二步:获取连续三场及更多获取奖牌的用户:两表关联,关联条件为user_id in (gold_medal,silver_medal,bronze_medal),然后使用row_Number()函数进行排名user_id分组,contest_Id 排序获得排名,使用contest_id减去排名,得到diff值,如果连续场次获得奖牌,diff是相同的,根据name,mail,diff进行分组,使用count()函数进行统计,获取count() 大于等于 3 的结果;

第三步:使用union将前两步结果进行联合输出,得到最终结果。

2.图解

六、代码实现

sql 复制代码
SELECT
    u.name,
    u.mail
from Contests c
join users u on c.gold_medal = u.user_id
GROUP BY u.name, u.mail
HAVING count(*) >= 3
union
(with t1 AS (
    SELECT
        u.name,
        u.mail,
        contest_id - row_number() OVER (partition by user_id ORDER BY contest_id) as diff
    from users u
    join contests c on user_id in (gold_medal,silver_medal,bronze_medal)
 )
 SELECT
    name,
    mail
from t1
GROUP BY name, mail,diff
HAVING count(*) >= 3
 );

七、总结

本题需求为寻找面试候选人,难点在于求连续三场及更多获得奖牌的用户:

求连续问题的通用思路为首先观察表中数据是否存在等差数列,如果存在等差数列,那只需要再创造一个等差数列即可,通常使用row_number() 排名函数获取等差数列,然后观察数据 ,求两个等差数列的差值,通过差值及其他字段进行分组,差值相同的即为连续的,通过差值及其他字段进行分组,使用count()函数统计差值相同的次数,过滤出满足题目需求的值即可。

相关推荐
Tisfy34 分钟前
LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))
算法·leetcode·题解·贪心·思维
DdddJMs__13537 分钟前
C语言 | Leetcode C语言题解之第564题寻找最近的回文数
c语言·leetcode·题解
"追风者"1 小时前
mysql数据库(六)pymysql、视图、触发器、存储过程、函数、流程控制、数据库连接池
数据库·mysql
HilariousDog1 小时前
Mysql数据库1——基本原理和基础操作
数据库·mysql·oracle
小诸葛的博客2 小时前
mysql中mvcc如何处理纯读事务的?
数据库·mysql
xxxmmc3 小时前
Leetcode 3355 Zero Array Transformation
算法·leetcode·差分
程序garbage3 小时前
搜索插入位置-力扣
数据结构·算法·leetcode
来知晓3 小时前
Python世界:力扣题解875,珂珂爱吃香蕉,中等
linux·python·leetcode
xiaoshiguang33 小时前
LeetCode 209 长度最小的子数组(滑动窗口)
java·算法·leetcode
m0_675988233 小时前
Leetcode3244:新增道路查询后的最短距离 II(C++)
c++·算法·leetcode