Skip to content

Commit 8965365

Browse files
authored
Added task 3617
1 parent 7d191f6 commit 8965365

File tree

3 files changed

+327
-0
lines changed
  • src
    • main/java/g3601_3700/s3617_find_students_with_study_spiral_pattern
    • test/java/g3601_3700/s3617_find_students_with_study_spiral_pattern

3 files changed

+327
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
3617\. Find Students with Study Spiral Pattern
2+
3+
Hard
4+
5+
Table: `students`
6+
7+
+--------------+---------+
8+
| Column Name | Type |
9+
+--------------+---------+
10+
| student_id | int |
11+
| student_name | varchar |
12+
| major | varchar |
13+
+--------------+---------+
14+
student_id is the unique identifier for this table.
15+
Each row contains information about a student and their academic major.
16+
17+
Table: `study_sessions`
18+
19+
+---------------+---------+
20+
| Column Name | Type |
21+
+---------------+---------+
22+
| session_id | int |
23+
| student_id | int |
24+
| subject | varchar |
25+
| session_date | date |
26+
| hours_studied | decimal |
27+
+---------------+---------+
28+
session_id is the unique identifier for this table.
29+
Each row represents a study session by a student for a specific subject.
30+
31+
Write a solution to find students who follow the **Study Spiral Pattern** - students who consistently study multiple subjects in a rotating cycle.
32+
33+
* A Study Spiral Pattern means a student studies at least `3` **different subjects** in a repeating sequence
34+
* The pattern must repeat for **at least** `2` **complete cycles** (minimum `6` study sessions)
35+
* Sessions must be **consecutive dates** with no gaps longer than `2` days between sessions
36+
* Calculate the **cycle length** (number of different subjects in the pattern)
37+
* Calculate the **total study hours** across all sessions in the pattern
38+
* Only include students with cycle length of **at least** `3` **subjects**
39+
40+
Return _the result table ordered by cycle length in **descending** order, then by total study hours in **descending** order_.
41+
42+
The result format is in the following example.
43+
44+
**Example:**
45+
46+
**Input:**
47+
48+
students table:
49+
50+
| student_id | student_name | major |
51+
|------------|--------------|-------------------|
52+
| 1 | Alice Chen | Computer Science |
53+
| 2 | Bob Johnson | Mathematics |
54+
| 3 | Carol Davis | Physics |
55+
| 4 | David Wilson | Chemistry |
56+
| 5 | Emma Brown | Biology |
57+
58+
study\_sessions table:
59+
60+
| session_id | student_id | subject | session_date | hours_studied |
61+
|------------|------------|------------|--------------|----------------|
62+
| 1 | 1 | Math | 2023-10-01 | 2.5 |
63+
| 2 | 1 | Physics | 2023-10-02 | 3.0 |
64+
| 3 | 1 | Chemistry | 2023-10-03 | 2.0 |
65+
| 4 | 1 | Math | 2023-10-04 | 2.5 |
66+
| 5 | 1 | Physics | 2023-10-05 | 3.0 |
67+
| 6 | 1 | Chemistry | 2023-10-06 | 2.0 |
68+
| 7 | 2 | Algebra | 2023-10-01 | 4.0 |
69+
| 8 | 2 | Calculus | 2023-10-02 | 3.5 |
70+
| 9 | 2 | Statistics | 2023-10-03 | 2.5 |
71+
| 10 | 2 | Geometry | 2023-10-04 | 3.0 |
72+
| 11 | 2 | Algebra | 2023-10-05 | 4.0 |
73+
| 12 | 2 | Calculus | 2023-10-06 | 3.5 |
74+
| 13 | 2 | Statistics | 2023-10-07 | 2.5 |
75+
| 14 | 2 | Geometry | 2023-10-08 | 3.0 |
76+
| 15 | 3 | Biology | 2023-10-01 | 2.0 |
77+
| 16 | 3 | Chemistry | 2023-10-02 | 2.5 |
78+
| 17 | 3 | Biology | 2023-10-03 | 2.0 |
79+
| 18 | 3 | Chemistry | 2023-10-04 | 2.5 |
80+
| 19 | 4 | Organic | 2023-10-01 | 3.0 |
81+
| 20 | 4 | Physical | 2023-10-05 | 2.5 |
82+
83+
**Output:**
84+
85+
| student_id | student_name | major | cycle_length | total_study_hours |
86+
|------------|--------------|-------------------|--------------|-------------------|
87+
| 2 | Bob Johnson | Mathematics | 4 | 26.0 |
88+
| 1 | Alice Chen | Computer Science | 3 | 15.0 |
89+
90+
**Explanation:**
91+
92+
* **Alice Chen (student\_id = 1):**
93+
* Study sequence: Math → Physics → Chemistry → Math → Physics → Chemistry
94+
* Pattern: 3 subjects (Math, Physics, Chemistry) repeating for 2 complete cycles
95+
* Consecutive dates: Oct 1-6 with no gaps > 2 days
96+
* Cycle length: 3 subjects
97+
* Total hours: 2.5 + 3.0 + 2.0 + 2.5 + 3.0 + 2.0 = 15.0 hours
98+
* **Bob Johnson (student\_id = 2):**
99+
* Study sequence: Algebra → Calculus → Statistics → Geometry → Algebra → Calculus → Statistics → Geometry
100+
* Pattern: 4 subjects (Algebra, Calculus, Statistics, Geometry) repeating for 2 complete cycles
101+
* Consecutive dates: Oct 1-8 with no gaps > 2 days
102+
* Cycle length: 4 subjects
103+
* Total hours: 4.0 + 3.5 + 2.5 + 3.0 + 4.0 + 3.5 + 2.5 + 3.0 = 26.0 hours
104+
* **Students not included:**
105+
* Carol Davis (student\_id = 3): Only 2 subjects (Biology, Chemistry) - doesn't meet minimum 3 subjects requirement
106+
* David Wilson (student\_id = 4): Only 2 study sessions with a 4-day gap - doesn't meet consecutive dates requirement
107+
* Emma Brown (student\_id = 5): No study sessions recorded
108+
109+
The result table is ordered by cycle\_length in descending order, then by total\_study\_hours in descending order.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Write your MySQL query statement below
2+
# #Hard #Database #2025_07_16_Time_553_ms_(100.00%)_Space_0.0_MB_(100.00%)
3+
-- WITH studentstudysummary AS (
4+
-- SELECT
5+
-- student_id,
6+
-- SUM(hours_studied) AS total_study_hours,
7+
-- COUNT(DISTINCT subject) AS cycle_length
8+
-- FROM
9+
-- study_sessions
10+
-- GROUP BY
11+
-- student_id
12+
-- HAVING
13+
-- COUNT(DISTINCT subject) >= 3
14+
-- ),
15+
-- rankedstudysessionswithgaps AS (
16+
-- SELECT
17+
-- ss.student_id,
18+
-- ss.subject,
19+
-- ss.session_date,
20+
-- DATEDIFF(
21+
-- LEAD(ss.session_date, 1, ss.session_date)
22+
-- OVER (PARTITION BY ss.student_id ORDER BY ss.session_date),
23+
-- ss.session_date
24+
-- ) AS gap_to_next_session,
25+
-- ROW_NUMBER() OVER (PARTITION BY ss.student_id ORDER BY ss.session_date) AS rn,
26+
-- sss.total_study_hours,
27+
-- sss.cycle_length
28+
-- FROM
29+
-- study_sessions ss
30+
-- INNER JOIN studentstudysummary sss
31+
-- ON ss.student_id = sss.student_id
32+
-- ),
33+
-- cyclicstudents AS (
34+
-- SELECT
35+
-- rss1.student_id,
36+
-- rss1.cycle_length,
37+
-- rss1.total_study_hours
38+
-- FROM
39+
-- rankedstudysessionswithgaps rss1
40+
-- INNER JOIN rankedstudysessionswithgaps rss2
41+
-- ON rss1.student_id = rss2.student_id
42+
-- AND rss2.rn = rss1.rn + rss1.cycle_length
43+
-- AND rss1.subject = rss2.subject
44+
-- WHERE
45+
-- rss1.gap_to_next_session < 3
46+
-- AND rss2.gap_to_next_session < 3
47+
-- GROUP BY
48+
-- rss1.student_id,
49+
-- rss1.cycle_length,
50+
-- rss1.total_study_hours
51+
-- HAVING
52+
-- COUNT(DISTINCT rss1.subject) >= 3
53+
-- )
54+
-- SELECT
55+
-- s.student_id,
56+
-- s.student_name,
57+
-- s.major,
58+
-- cs.cycle_length,
59+
-- cs.total_study_hours
60+
-- FROM
61+
-- cyclicstudents cs
62+
-- INNER JOIN students s
63+
-- ON cs.student_id = s.student_id
64+
-- ORDER BY
65+
-- cs.cycle_length DESC,
66+
-- cs.total_study_hours DESC;
67+
WITH studentstudysummary AS (
68+
SELECT
69+
student_id,
70+
SUM(hours_studied) AS total_study_hours,
71+
COUNT(DISTINCT subject) AS cycle_length
72+
FROM study_sessions
73+
GROUP BY student_id
74+
HAVING COUNT(DISTINCT subject) >= 3
75+
),
76+
rankedstudysessionswithgaps AS (
77+
SELECT
78+
ss.student_id,
79+
ss.subject,
80+
ss.session_date,
81+
DATEDIFF('DAY',
82+
ss.session_date,
83+
LEAD(ss.session_date, 1, ss.session_date) OVER (
84+
PARTITION BY ss.student_id ORDER BY ss.session_date
85+
)
86+
) AS gap_to_next_session,
87+
ROW_NUMBER() OVER (PARTITION BY ss.student_id ORDER BY ss.session_date) AS rn,
88+
sss.total_study_hours,
89+
sss.cycle_length
90+
FROM study_sessions ss
91+
INNER JOIN studentstudysummary sss
92+
ON ss.student_id = sss.student_id
93+
),
94+
cyclicstudents AS (
95+
SELECT
96+
rss1.student_id,
97+
rss1.cycle_length,
98+
rss1.total_study_hours
99+
FROM rankedstudysessionswithgaps rss1
100+
INNER JOIN rankedstudysessionswithgaps rss2
101+
ON rss1.student_id = rss2.student_id
102+
AND rss2.rn = rss1.rn + rss1.cycle_length
103+
AND rss1.subject = rss2.subject
104+
WHERE
105+
rss1.gap_to_next_session < 3
106+
AND rss2.gap_to_next_session < 3
107+
GROUP BY
108+
rss1.student_id,
109+
rss1.cycle_length,
110+
rss1.total_study_hours
111+
HAVING
112+
COUNT(DISTINCT rss1.subject) >= 3
113+
)
114+
SELECT
115+
s.student_id,
116+
s.student_name,
117+
s.major,
118+
cs.cycle_length,
119+
cs.total_study_hours
120+
FROM cyclicstudents cs
121+
INNER JOIN students s ON cs.student_id = s.student_id
122+
ORDER BY cs.cycle_length DESC, cs.total_study_hours DESC;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package g3601_3700.s3617_find_students_with_study_spiral_pattern;
2+
3+
import static org.hamcrest.CoreMatchers.equalTo;
4+
import static org.hamcrest.MatcherAssert.assertThat;
5+
6+
import java.io.BufferedReader;
7+
import java.io.FileNotFoundException;
8+
import java.io.FileReader;
9+
import java.sql.Connection;
10+
import java.sql.ResultSet;
11+
import java.sql.SQLException;
12+
import java.sql.Statement;
13+
import java.util.stream.Collectors;
14+
import javax.sql.DataSource;
15+
import org.junit.jupiter.api.Test;
16+
import org.zapodot.junit.db.annotations.EmbeddedDatabase;
17+
import org.zapodot.junit.db.annotations.EmbeddedDatabaseTest;
18+
import org.zapodot.junit.db.common.CompatibilityMode;
19+
20+
@EmbeddedDatabaseTest(
21+
compatibilityMode = CompatibilityMode.MySQL,
22+
initialSqls =
23+
"CREATE TABLE students ("
24+
+ " student_id INT PRIMARY KEY,"
25+
+ " student_name VARCHAR(50),"
26+
+ " major VARCHAR(50)"
27+
+ ");"
28+
+ "INSERT INTO students (student_id, student_name, major) VALUES"
29+
+ "(1, 'Alice Chen', 'Computer Science'),"
30+
+ "(2, 'Bob Johnson', 'Mathematics'),"
31+
+ "(3, 'Carol Davis', 'Physics'),"
32+
+ "(4, 'David Wilson', 'Chemistry'),"
33+
+ "(5, 'Emma Brown', 'Biology');"
34+
+ "CREATE TABLE study_sessions ("
35+
+ " session_id INT PRIMARY KEY,"
36+
+ " student_id INT,"
37+
+ " subject VARCHAR(30),"
38+
+ " session_date DATE,"
39+
+ " hours_studied DECIMAL(3,1)"
40+
+ ");"
41+
+ "INSERT INTO study_sessions (session_id, student_id, "
42+
+ "subject, session_date, hours_studied) VALUES"
43+
+ "(1, 1, 'Math', '2023-10-01', 2.5),"
44+
+ "(2, 1, 'Physics', '2023-10-02', 3.0),"
45+
+ "(3, 1, 'Chemistry', '2023-10-03', 2.0),"
46+
+ "(4, 1, 'Math', '2023-10-04', 2.5),"
47+
+ "(5, 1, 'Physics', '2023-10-05', 3.0),"
48+
+ "(6, 1, 'Chemistry', '2023-10-06', 2.0),"
49+
+ "(7, 2, 'Algebra', '2023-10-01', 4.0),"
50+
+ "(8, 2, 'Calculus', '2023-10-02', 3.5),"
51+
+ "(9, 2, 'Statistics', '2023-10-03', 2.5),"
52+
+ "(10, 2, 'Geometry', '2023-10-04', 3.0),"
53+
+ "(11, 2, 'Algebra', '2023-10-05', 4.0),"
54+
+ "(12, 2, 'Calculus', '2023-10-06', 3.5),"
55+
+ "(13, 2, 'Statistics','2023-10-07', 2.5),"
56+
+ "(14, 2, 'Geometry', '2023-10-08', 3.0),"
57+
+ "(15, 3, 'Biology', '2023-10-01', 2.0),"
58+
+ "(16, 3, 'Chemistry', '2023-10-02', 2.5),"
59+
+ "(17, 3, 'Biology', '2023-10-03', 2.0),"
60+
+ "(18, 3, 'Chemistry', '2023-10-04', 2.5),"
61+
+ "(19, 4, 'Organic', '2023-10-01', 3.0),"
62+
+ "(20, 4, 'Physical', '2023-10-05', 2.5);")
63+
class MysqlTest {
64+
@Test
65+
void testScript(@EmbeddedDatabase DataSource dataSource)
66+
throws SQLException, FileNotFoundException {
67+
try (final Connection connection = dataSource.getConnection()) {
68+
try (final Statement statement = connection.createStatement();
69+
final ResultSet resultSet =
70+
statement.executeQuery(
71+
new BufferedReader(
72+
new FileReader(
73+
"src/main/java/g3601_3700/"
74+
+ "s3617_find_students_with_"
75+
+ "study_spiral_pattern/"
76+
+ "script.sql"))
77+
.lines()
78+
.collect(Collectors.joining("\n"))
79+
.replaceAll("#.*?\\r?\\n", ""))) {
80+
assertThat(resultSet.next(), equalTo(true));
81+
assertThat(resultSet.getNString(1), equalTo("2"));
82+
assertThat(resultSet.getNString(2), equalTo("Bob Johnson"));
83+
assertThat(resultSet.getNString(3), equalTo("Mathematics"));
84+
assertThat(resultSet.getNString(4), equalTo("4"));
85+
assertThat(resultSet.getNString(5), equalTo("26.0"));
86+
assertThat(resultSet.next(), equalTo(true));
87+
assertThat(resultSet.getNString(1), equalTo("1"));
88+
assertThat(resultSet.getNString(2), equalTo("Alice Chen"));
89+
assertThat(resultSet.getNString(3), equalTo("Computer Science"));
90+
assertThat(resultSet.getNString(4), equalTo("3"));
91+
assertThat(resultSet.getNString(5), equalTo("15.0"));
92+
assertThat(resultSet.next(), equalTo(false));
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)