|
| 1 | +--- |
| 2 | +comments: true |
| 3 | +difficulty: Medium |
| 4 | +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README_EN.md |
| 5 | +tags: |
| 6 | + - Database |
| 7 | +--- |
| 8 | + |
| 9 | +<!-- problem:start --> |
| 10 | + |
| 11 | +# [3421. Find Students Who Improved](https://leetcode.com/problems/find-students-who-improved) |
| 12 | + |
| 13 | +[中文文档](/solution/3400-3499/3421.Find%20Students%20Who%20Improved/README.md) |
| 14 | + |
| 15 | +## Description |
| 16 | + |
| 17 | +<!-- description:start --> |
| 18 | + |
| 19 | +<p>Table: <code>Scores</code></p> |
| 20 | + |
| 21 | +<pre> |
| 22 | ++-------------+---------+ |
| 23 | +| Column Name | Type | |
| 24 | ++-------------+---------+ |
| 25 | +| student_id | int | |
| 26 | +| subject | varchar | |
| 27 | +| score | int | |
| 28 | +| exam_date | varchar | |
| 29 | ++-------------+---------+ |
| 30 | +(student_id, subject, exam_date) is the primary key for this table. |
| 31 | +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). |
| 32 | +</pre> |
| 33 | + |
| 34 | +<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> |
| 35 | + |
| 36 | +<ul> |
| 37 | + <li>Have taken exams in the <strong>same subject</strong> on at least two different dates</li> |
| 38 | + <li>Their <strong>latest score</strong> in that subject is <strong>higher</strong> than their <strong>first score</strong></li> |
| 39 | +</ul> |
| 40 | + |
| 41 | +<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> |
| 42 | + |
| 43 | +<p>The result format is in the following example.</p> |
| 44 | + |
| 45 | +<p> </p> |
| 46 | +<p><strong class="example">Example:</strong></p> |
| 47 | + |
| 48 | +<div class="example-block"> |
| 49 | +<p><strong>Input:</strong></p> |
| 50 | + |
| 51 | +<p>Scores table:</p> |
| 52 | + |
| 53 | +<pre class="example-io"> |
| 54 | ++------------+----------+-------+------------+ |
| 55 | +| student_id | subject | score | exam_date | |
| 56 | ++------------+----------+-------+------------+ |
| 57 | +| 101 | Math | 70 | 15-01-2023 | |
| 58 | +| 101 | Math | 85 | 15-02-2023 | |
| 59 | +| 101 | Physics | 65 | 15-01-2023 | |
| 60 | +| 101 | Physics | 60 | 15-02-2023 | |
| 61 | +| 102 | Math | 80 | 15-01-2023 | |
| 62 | +| 102 | Math | 85 | 15-02-2023 | |
| 63 | +| 103 | Math | 90 | 15-01-2023 | |
| 64 | +| 104 | Physics | 75 | 15-01-2023 | |
| 65 | +| 104 | Physics | 85 | 15-02-2023 | |
| 66 | ++------------+----------+-------+------------+ |
| 67 | +</pre> |
| 68 | + |
| 69 | +<p><strong>Output:</strong></p> |
| 70 | + |
| 71 | +<pre class="example-io"> |
| 72 | ++------------+----------+-------------+--------------+ |
| 73 | +| student_id | subject | first_score | latest_score | |
| 74 | ++------------+----------+-------------+--------------+ |
| 75 | +| 101 | Math | 70 | 85 | |
| 76 | +| 102 | Math | 80 | 85 | |
| 77 | +| 104 | Physics | 75 | 85 | |
| 78 | ++------------+----------+-------------+--------------+ |
| 79 | +</pre> |
| 80 | + |
| 81 | +<p><strong>Explanation:</strong></p> |
| 82 | + |
| 83 | +<ul> |
| 84 | + <li>Student 101 in Math: Improved from 70 to 85</li> |
| 85 | + <li>Student 101 in Physics: No improvement (dropped from 65 to 60)</li> |
| 86 | + <li>Student 102 in Math: Improved from 80 to 85</li> |
| 87 | + <li>Student 103 in Math: Only one exam, not eligible</li> |
| 88 | + <li>Student 104 in Physics: Improved from 75 to 85</li> |
| 89 | +</ul> |
| 90 | + |
| 91 | +<p>Result table is ordered by student_id, subject.</p> |
| 92 | +</div> |
| 93 | + |
| 94 | +<!-- description:end --> |
| 95 | + |
| 96 | +## Solutions |
| 97 | + |
| 98 | +<!-- solution:start --> |
| 99 | + |
| 100 | +### Solution 1: Window Function + Subquery + Conditional Filtering |
| 101 | + |
| 102 | +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. |
| 103 | + |
| 104 | +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. |
| 105 | + |
| 106 | +<!-- tabs:start --> |
| 107 | + |
| 108 | +#### MySQL |
| 109 | + |
| 110 | +```sql |
| 111 | +WITH |
| 112 | + RankedScores AS ( |
| 113 | + SELECT |
| 114 | + student_id, |
| 115 | + subject, |
| 116 | + score, |
| 117 | + exam_date, |
| 118 | + ROW_NUMBER() OVER ( |
| 119 | + PARTITION BY student_id, subject |
| 120 | + ORDER BY exam_date ASC |
| 121 | + ) AS rn_first, |
| 122 | + ROW_NUMBER() OVER ( |
| 123 | + PARTITION BY student_id, subject |
| 124 | + ORDER BY exam_date DESC |
| 125 | + ) AS rn_latest |
| 126 | + FROM Scores |
| 127 | + ), |
| 128 | + FirstAndLatestScores AS ( |
| 129 | + SELECT |
| 130 | + f.student_id, |
| 131 | + f.subject, |
| 132 | + f.score AS first_score, |
| 133 | + l.score AS latest_score |
| 134 | + FROM |
| 135 | + RankedScores f |
| 136 | + JOIN RankedScores l ON f.student_id = l.student_id AND f.subject = l.subject |
| 137 | + WHERE f.rn_first = 1 AND l.rn_latest = 1 |
| 138 | + ) |
| 139 | +SELECT |
| 140 | + * |
| 141 | +FROM FirstAndLatestScores |
| 142 | +WHERE latest_score > first_score |
| 143 | +ORDER BY 1, 2; |
| 144 | +``` |
| 145 | + |
| 146 | +<!-- tabs:end --> |
| 147 | + |
| 148 | +<!-- solution:end --> |
| 149 | + |
| 150 | +<!-- problem:end --> |
0 commit comments