Skip to content

Commit cd8173e

Browse files
committed
Added task 3586
1 parent bb9c4e9 commit cd8173e

File tree

3 files changed

+258
-0
lines changed

3 files changed

+258
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
3586\. Find COVID Recovery Patients
2+
3+
Medium
4+
5+
Table: `patients`
6+
7+
+-------------+---------+
8+
| Column Name | Type |
9+
+-------------+---------+
10+
| patient_id | int |
11+
| patient_name| varchar |
12+
| age | int |
13+
+-------------+---------+
14+
patient_id is the unique identifier for this table.
15+
Each row contains information about a patient.
16+
17+
Table: `covid_tests`
18+
19+
+-------------+---------+
20+
| Column Name | Type |
21+
+-------------+---------+
22+
| test_id | int |
23+
| patient_id | int |
24+
| test_date | date |
25+
| result | varchar |
26+
+-------------+---------+
27+
test_id is the unique identifier for this table.
28+
Each row represents a COVID test result. The result can be Positive, Negative, or Inconclusive.
29+
30+
Write a solution to find patients who have **recovered from COVID** - patients who tested positive but later tested negative.
31+
32+
* A patient is considered recovered if they have **at least one** **Positive** test followed by at least one **Negative** test on a **later date**
33+
* Calculate the **recovery time** in days as the **difference** between the **first positive test** and the **first negative test** after that **positive test**
34+
* **Only include** patients who have both positive and negative test results
35+
36+
Return _the result table ordered by_ `recovery_time` _in **ascending** order, then by_ `patient_name` _in **ascending** order_.
37+
38+
The result format is in the following example.
39+
40+
**Example:**
41+
42+
**Input:**
43+
44+
patients table:
45+
46+
+------------+--------------+-----+
47+
| patient_id | patient_name | age |
48+
+------------+--------------+-----+
49+
| 1 | Alice Smith | 28 |
50+
| 2 | Bob Johnson | 35 |
51+
| 3 | Carol Davis | 42 |
52+
| 4 | David Wilson | 31 |
53+
| 5 | Emma Brown | 29 |
54+
+------------+--------------+-----+
55+
56+
covid\_tests table:
57+
58+
+---------+------------+------------+--------------+
59+
| test_id | patient_id | test_date | result |
60+
|---------|------------|------------|--------------|
61+
| 1 | 1 | 2023-01-15 | Positive |
62+
| 2 | 1 | 2023-01-25 | Negative |
63+
| 3 | 2 | 2023-02-01 | Positive |
64+
| 4 | 2 | 2023-02-05 | Inconclusive |
65+
| 5 | 2 | 2023-02-12 | Negative |
66+
| 6 | 3 | 2023-01-20 | Negative |
67+
| 7 | 3 | 2023-02-10 | Positive |
68+
| 8 | 3 | 2023-02-20 | Negative |
69+
| 9 | 4 | 2023-01-10 | Positive |
70+
| 10 | 4 | 2023-01-18 | Positive |
71+
| 11 | 5 | 2023-02-15 | Negative |
72+
| 12 | 5 | 2023-02-20 | Negative |
73+
+---------+------------+------------+--------------+
74+
75+
**Output:**
76+
77+
+------------+--------------+-----+---------------+
78+
| patient_id | patient_name | age | recovery_time |
79+
|------------|--------------|-----|---------------|
80+
| 1 | Alice Smith | 28 | 10 |
81+
| 3 | Carol Davis | 42 | 10 |
82+
| 2 | Bob Johnson | 35 | 11 |
83+
+------------+--------------+-----+---------------+
84+
85+
**Explanation:**
86+
87+
* **Alice Smith (patient\_id = 1):**
88+
* First positive test: 2023-01-15
89+
* First negative test after positive: 2023-01-25
90+
* Recovery time: 25 - 15 = 10 days
91+
* **Bob Johnson (patient\_id = 2):**
92+
* First positive test: 2023-02-01
93+
* Inconclusive test on 2023-02-05 (ignored for recovery calculation)
94+
* First negative test after positive: 2023-02-12
95+
* Recovery time: 12 - 1 = 11 days
96+
* **Carol Davis (patient\_id = 3):**
97+
* Had negative test on 2023-01-20 (before positive test)
98+
* First positive test: 2023-02-10
99+
* First negative test after positive: 2023-02-20
100+
* Recovery time: 20 - 10 = 10 days
101+
* **Patients not included:**
102+
* David Wilson (patient\_id = 4): Only has positive tests, no negative test after positive
103+
* Emma Brown (patient\_id = 5): Only has negative tests, never tested positive
104+
105+
Output table is ordered by recovery\_time in ascending order, and then by patient\_name in ascending order.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Write your MySQL query statement below
2+
# #Medium #Database #2025_06_19_Time_471_ms_(97.17%)_Space_0.0_MB_(100.00%)
3+
-- mysql
4+
-- SELECT
5+
-- p.patient_id,
6+
-- p.patient_name,
7+
-- p.age,
8+
-- DATEDIFF(
9+
-- min(neg.test_date),
10+
-- min(pos.test_date)
11+
-- ) AS recovery_time
12+
-- FROM
13+
-- patients p
14+
-- JOIN covid_tests pos ON
15+
-- p.patient_id = pos.patient_id AND pos.result = 'Positive'
16+
-- JOIN covid_tests neg ON
17+
-- p.patient_id = neg.patient_id AND neg.result = 'Negative'
18+
-- WHERE
19+
-- neg.test_date > pos.test_date
20+
-- GROUP BY
21+
-- p.patient_id, p.patient_name, p.age
22+
-- ORDER BY
23+
-- recovery_time, p.patient_name;
24+
select
25+
p.patient_id,
26+
p.patient_name,
27+
p.age,
28+
datediff(
29+
day,
30+
pos.first_pos_date,
31+
neg.first_neg_date
32+
) as recovery_time
33+
from
34+
patients p
35+
join (
36+
select patient_id, min(test_date) as first_pos_date
37+
from covid_tests
38+
where result = 'Positive'
39+
group by patient_id
40+
) pos on p.patient_id = pos.patient_id
41+
join (
42+
select
43+
c1.patient_id,
44+
min(c1.test_date) as first_neg_date
45+
from
46+
covid_tests c1
47+
join (
48+
select patient_id, min(test_date) as first_pos_date
49+
from covid_tests
50+
where result = 'Positive'
51+
group by patient_id
52+
) p2 on c1.patient_id = p2.patient_id
53+
where
54+
c1.result = 'Negative'
55+
and c1.test_date > p2.first_pos_date
56+
group by c1.patient_id
57+
) neg on p.patient_id = neg.patient_id
58+
order by
59+
recovery_time ASC, p.patient_name ASC;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package g3501_3600.s3586_find_covid_recovery_patients
2+
3+
import org.hamcrest.CoreMatchers.equalTo
4+
import org.hamcrest.MatcherAssert.assertThat
5+
import org.junit.jupiter.api.Test
6+
import org.zapodot.junit.db.annotations.EmbeddedDatabase
7+
import org.zapodot.junit.db.annotations.EmbeddedDatabaseTest
8+
import org.zapodot.junit.db.common.CompatibilityMode
9+
import java.io.BufferedReader
10+
import java.io.FileNotFoundException
11+
import java.io.FileReader
12+
import java.sql.SQLException
13+
import java.util.stream.Collectors
14+
import javax.sql.DataSource
15+
16+
@EmbeddedDatabaseTest(
17+
compatibilityMode = CompatibilityMode.MySQL,
18+
initialSqls = [
19+
(
20+
"CREATE TABLE patients (patient_id INTEGER, patient_name VARCHAR(255), age INTEGER); " +
21+
"INSERT INTO patients (patient_id, patient_name, age) VALUES" +
22+
"(1, 'Alice Smith', 28)," +
23+
"(2, 'Bob Johnson', 35)," +
24+
"(3, 'Carol Davis', 42)," +
25+
"(4, 'David Wilson', 31)," +
26+
"(5, 'Emma Brown', 29);" +
27+
"CREATE TABLE covid_tests (test_id INTEGER, patient_id INTEGER" +
28+
", test_date DATE, result VARCHAR(255)); " +
29+
"INSERT INTO covid_tests (test_id, patient_id, test_date, result) VALUES" +
30+
"(1, 1, '2023-01-15', 'Positive')," +
31+
"(2, 1, '2023-01-25', 'Negative')," +
32+
"(3, 2, '2023-02-01', 'Positive')," +
33+
"(4, 2, '2023-02-05', 'Inconclusive')," +
34+
"(5, 2, '2023-02-12', 'Negative')," +
35+
"(6, 3, '2023-01-20', 'Negative')," +
36+
"(7, 3, '2023-02-10', 'Positive')," +
37+
"(8, 3, '2023-02-20', 'Negative')," +
38+
"(9, 4, '2023-01-10', 'Positive')," +
39+
"(10, 4, '2023-01-18', 'Positive')," +
40+
"(11, 5, '2023-02-15', 'Negative')," +
41+
"(12, 5, '2023-02-20', 'Negative');"
42+
),
43+
],
44+
)
45+
internal class MysqlTest {
46+
@Test
47+
@Throws(SQLException::class, FileNotFoundException::class)
48+
fun testScript(@EmbeddedDatabase dataSource: DataSource) {
49+
dataSource.connection.use { connection ->
50+
connection.createStatement().use { statement ->
51+
statement.executeQuery(
52+
BufferedReader(
53+
FileReader(
54+
(
55+
"src/main/kotlin/g3501_3600/" +
56+
"s3586_find_covid_recovery_patients/" +
57+
"script.sql"
58+
),
59+
),
60+
)
61+
.lines()
62+
.collect(Collectors.joining("\n"))
63+
.replace("#.*\\r\\n".toRegex(), ""),
64+
).use { resultSet ->
65+
assertThat<Boolean>(resultSet.next(), equalTo<Boolean>(true))
66+
assertThat<String>(resultSet.getNString(1), equalTo<String>("1"))
67+
assertThat<String>(
68+
resultSet.getNString(2),
69+
equalTo<String>("Alice Smith"),
70+
)
71+
assertThat<String>(resultSet.getNString(3), equalTo<String>("28"))
72+
assertThat<String>(resultSet.getNString(4), equalTo<String>("10"))
73+
assertThat<Boolean>(resultSet.next(), equalTo<Boolean>(true))
74+
assertThat<String>(resultSet.getNString(1), equalTo<String>("3"))
75+
assertThat<String>(
76+
resultSet.getNString(2),
77+
equalTo<String>("Carol Davis"),
78+
)
79+
assertThat<String>(resultSet.getNString(3), equalTo<String>("42"))
80+
assertThat<String>(resultSet.getNString(4), equalTo<String>("10"))
81+
assertThat<Boolean>(resultSet.next(), equalTo<Boolean>(true))
82+
assertThat<String>(resultSet.getNString(1), equalTo<String>("2"))
83+
assertThat<String>(
84+
resultSet.getNString(2),
85+
equalTo<String>("Bob Johnson"),
86+
)
87+
assertThat<String>(resultSet.getNString(3), equalTo<String>("35"))
88+
assertThat<String>(resultSet.getNString(4), equalTo<String>("11"))
89+
assertThat<Boolean>(resultSet.next(), equalTo<Boolean>(false))
90+
}
91+
}
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)