-
-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add solutions to lc problem: No.3421
No.3421.Find Students Who Improved
- Loading branch information
Showing
8 changed files
with
340 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
151 changes: 151 additions & 0 deletions
151
solution/3400-3499/3421.Find Students Who Improved/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
--- | ||
comments: true | ||
difficulty: 中等 | ||
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md | ||
tags: | ||
- 数据库 | ||
--- | ||
|
||
<!-- problem:start --> | ||
|
||
# [3421. 查找进步的学生](https://leetcode.cn/problems/find-students-who-improved) | ||
|
||
[English Version](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md) | ||
|
||
## 题目描述 | ||
|
||
<!-- description:start --> | ||
|
||
<p>表:<code>Scores</code></p> | ||
|
||
<pre> | ||
+-------------+---------+ | ||
| Column Name | Type | | ||
+-------------+---------+ | ||
| student_id | int | | ||
| subject | varchar | | ||
| score | int | | ||
| exam_date | varchar | | ||
+-------------+---------+ | ||
(student_id, subject, exam_date) 是这张表的主键。 | ||
每一行包含有关学生在特定考试日期特定科目成绩的信息。分数范围从 0 到 100(包括边界)。 | ||
</pre> | ||
|
||
<p>编写一个解决方案来查找 <strong>进步的学生</strong>。如果 <strong>同时</strong> 满足以下两个条件,则该学生被认为是进步的:</p> | ||
|
||
<ul> | ||
<li>在 <strong>同一科目</strong> 至少有两个不同日期的考试。</li> | ||
<li>他们在该学科 <strong>最近的分数</strong> 比他们 <strong>第一次的分数更高。</strong></li> | ||
</ul> | ||
|
||
<p>返回结果表以 <code>student_id</code>,<code>subject</code> <strong>升序</strong> 排序。</p> | ||
|
||
<p>结果格式如下所示。</p> | ||
|
||
<p> </p> | ||
|
||
<p><strong class="example">示例:</strong></p> | ||
|
||
<div class="example-block"> | ||
<p><strong>输入:</strong></p> | ||
|
||
<p>Scores 表:</p> | ||
|
||
<pre class="example-io"> | ||
+------------+----------+-------+------------+ | ||
| student_id | subject | score | exam_date | | ||
+------------+----------+-------+------------+ | ||
| 101 | Math | 70 | 15-01-2023 | | ||
| 101 | Math | 85 | 15-02-2023 | | ||
| 101 | Physics | 65 | 15-01-2023 | | ||
| 101 | Physics | 60 | 15-02-2023 | | ||
| 102 | Math | 80 | 15-01-2023 | | ||
| 102 | Math | 85 | 15-02-2023 | | ||
| 103 | Math | 90 | 15-01-2023 | | ||
| 104 | Physics | 75 | 15-01-2023 | | ||
| 104 | Physics | 85 | 15-02-2023 | | ||
+------------+----------+-------+------------+ | ||
</pre> | ||
|
||
<p><strong>输出:</strong></p> | ||
|
||
<pre class="example-io"> | ||
+------------+----------+-------------+--------------+ | ||
| student_id | subject | first_score | latest_score | | ||
+------------+----------+-------------+--------------+ | ||
| 101 | Math | 70 | 85 | | ||
| 102 | Math | 80 | 85 | | ||
| 104 | Physics | 75 | 85 | | ||
+------------+----------+-------------+--------------+ | ||
</pre> | ||
|
||
<p><strong>解释:</strong></p> | ||
|
||
<ul> | ||
<li>学生 101 的数学:从 70 分进步到 85 分。</li> | ||
<li>学生 101 的物理:没有进步(从 65 分退步到 60分)</li> | ||
<li>学生 102 的数学:从 80 进步到 85 分。</li> | ||
<li>学生 103 的数学:只有一次考试,不符合资格。</li> | ||
<li>学生 104 in Physics:从 75 分进步到 85 分。</li> | ||
</ul> | ||
|
||
<p>结果表以 student_id,subject 升序排序。</p> | ||
</div> | ||
|
||
<!-- description:end --> | ||
|
||
## 解法 | ||
|
||
<!-- solution:start --> | ||
|
||
### 方法一:窗口函数 + 子连接 + 条件过滤 | ||
|
||
首先,我们使用窗口函数 `ROW_NUMBER()` 计算每个学生在每个科目中的考试日期的排名,分别计算出每个学生在每个科目中的第一次考试和最近一次考试的排名。 | ||
|
||
然后,我们使用子连接 `JOIN` 操作将第一次考试和最近一次考试的分数连接在一起,最后根据题目要求筛选出最近一次考试的分数比第一次考试的分数高的学生。 | ||
|
||
<!-- tabs:start --> | ||
|
||
#### MySQL | ||
|
||
```sql | ||
WITH | ||
RankedScores AS ( | ||
SELECT | ||
student_id, | ||
subject, | ||
score, | ||
exam_date, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date ASC | ||
) AS rn_first, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date DESC | ||
) AS rn_latest | ||
FROM Scores | ||
), | ||
FirstAndLatestScores AS ( | ||
SELECT | ||
f.student_id, | ||
f.subject, | ||
f.score AS first_score, | ||
l.score AS latest_score | ||
FROM | ||
RankedScores f | ||
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject | ||
WHERE f.rn_first = 1 AND l.rn_latest = 1 | ||
) | ||
SELECT | ||
* | ||
FROM FirstAndLatestScores | ||
WHERE latest_score > first_score | ||
ORDER BY 1, 2; | ||
``` | ||
|
||
<!-- tabs:end --> | ||
|
||
<!-- solution:end --> | ||
|
||
<!-- problem:end --> |
150 changes: 150 additions & 0 deletions
150
solution/3400-3499/3421.Find Students Who Improved/README_EN.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
--- | ||
comments: true | ||
difficulty: Medium | ||
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md | ||
tags: | ||
- Database | ||
--- | ||
|
||
<!-- problem:start --> | ||
|
||
# [3421. Find Students Who Improved](https://leetcode.com/problems/find-students-who-improved) | ||
|
||
[中文文档](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) | ||
|
||
## Description | ||
|
||
<!-- description:start --> | ||
|
||
<p>Table: <code>Scores</code></p> | ||
|
||
<pre> | ||
+-------------+---------+ | ||
| Column Name | Type | | ||
+-------------+---------+ | ||
| student_id | int | | ||
| subject | varchar | | ||
| score | int | | ||
| exam_date | varchar | | ||
+-------------+---------+ | ||
(student_id, subject, exam_date) is the primary key for this table. | ||
Each row contains information about a student's score in a specific subject on a particular exam date. score is between 0 and 100 (inclusive). | ||
</pre> | ||
|
||
<p>Write a solution to find the <strong>students who have shown improvement</strong>. A student is considered to have shown improvement if they meet <strong>both</strong> of these conditions:</p> | ||
|
||
<ul> | ||
<li>Have taken exams in the <strong>same subject</strong> on at least two different dates</li> | ||
<li>Their <strong>latest score</strong> in that subject is <strong>higher</strong> than their <strong>first score</strong></li> | ||
</ul> | ||
|
||
<p>Return <em>the result table</em> <em>ordered by</em> <code>student_id,</code> <code>subject</code> <em>in <strong>ascending</strong> order</em>.</p> | ||
|
||
<p>The result format is in the following example.</p> | ||
|
||
<p> </p> | ||
<p><strong class="example">Example:</strong></p> | ||
|
||
<div class="example-block"> | ||
<p><strong>Input:</strong></p> | ||
|
||
<p>Scores table:</p> | ||
|
||
<pre class="example-io"> | ||
+------------+----------+-------+------------+ | ||
| student_id | subject | score | exam_date | | ||
+------------+----------+-------+------------+ | ||
| 101 | Math | 70 | 15-01-2023 | | ||
| 101 | Math | 85 | 15-02-2023 | | ||
| 101 | Physics | 65 | 15-01-2023 | | ||
| 101 | Physics | 60 | 15-02-2023 | | ||
| 102 | Math | 80 | 15-01-2023 | | ||
| 102 | Math | 85 | 15-02-2023 | | ||
| 103 | Math | 90 | 15-01-2023 | | ||
| 104 | Physics | 75 | 15-01-2023 | | ||
| 104 | Physics | 85 | 15-02-2023 | | ||
+------------+----------+-------+------------+ | ||
</pre> | ||
|
||
<p><strong>Output:</strong></p> | ||
|
||
<pre class="example-io"> | ||
+------------+----------+-------------+--------------+ | ||
| student_id | subject | first_score | latest_score | | ||
+------------+----------+-------------+--------------+ | ||
| 101 | Math | 70 | 85 | | ||
| 102 | Math | 80 | 85 | | ||
| 104 | Physics | 75 | 85 | | ||
+------------+----------+-------------+--------------+ | ||
</pre> | ||
|
||
<p><strong>Explanation:</strong></p> | ||
|
||
<ul> | ||
<li>Student 101 in Math: Improved from 70 to 85</li> | ||
<li>Student 101 in Physics: No improvement (dropped from 65 to 60)</li> | ||
<li>Student 102 in Math: Improved from 80 to 85</li> | ||
<li>Student 103 in Math: Only one exam, not eligible</li> | ||
<li>Student 104 in Physics: Improved from 75 to 85</li> | ||
</ul> | ||
|
||
<p>Result table is ordered by student_id, subject.</p> | ||
</div> | ||
|
||
<!-- description:end --> | ||
|
||
## Solutions | ||
|
||
<!-- solution:start --> | ||
|
||
### Solution 1: Window Function + Subquery + Conditional Filtering | ||
|
||
First, we use the window function `ROW_NUMBER()` to calculate the ranking of each student's exam date in each subject, separately calculating the first and most recent exam rankings for each student in each subject. | ||
|
||
Then, we use a subquery `JOIN` operation to join the scores of the first and most recent exams together. Finally, we filter out the students whose most recent exam scores are higher than their first exam scores according to the problem requirements. | ||
|
||
<!-- tabs:start --> | ||
|
||
#### MySQL | ||
|
||
```sql | ||
WITH | ||
RankedScores AS ( | ||
SELECT | ||
student_id, | ||
subject, | ||
score, | ||
exam_date, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date ASC | ||
) AS rn_first, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date DESC | ||
) AS rn_latest | ||
FROM Scores | ||
), | ||
FirstAndLatestScores AS ( | ||
SELECT | ||
f.student_id, | ||
f.subject, | ||
f.score AS first_score, | ||
l.score AS latest_score | ||
FROM | ||
RankedScores f | ||
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject | ||
WHERE f.rn_first = 1 AND l.rn_latest = 1 | ||
) | ||
SELECT | ||
* | ||
FROM FirstAndLatestScores | ||
WHERE latest_score > first_score | ||
ORDER BY 1, 2; | ||
``` | ||
|
||
<!-- tabs:end --> | ||
|
||
<!-- solution:end --> | ||
|
||
<!-- problem:end --> |
33 changes: 33 additions & 0 deletions
33
solution/3400-3499/3421.Find Students Who Improved/Solution.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
WITH | ||
RankedScores AS ( | ||
SELECT | ||
student_id, | ||
subject, | ||
score, | ||
exam_date, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date ASC | ||
) AS rn_first, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY student_id, subject | ||
ORDER BY exam_date DESC | ||
) AS rn_latest | ||
FROM Scores | ||
), | ||
FirstAndLatestScores AS ( | ||
SELECT | ||
f.student_id, | ||
f.subject, | ||
f.score AS first_score, | ||
l.score AS latest_score | ||
FROM | ||
RankedScores f | ||
JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject | ||
WHERE f.rn_first = 1 AND l.rn_latest = 1 | ||
) | ||
SELECT | ||
* | ||
FROM FirstAndLatestScores | ||
WHERE latest_score > first_score | ||
ORDER BY 1, 2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters