Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bc61827

Browse files
Merge pull request #90 from iamAntimPal/Branch-1
Branch 1
2 parents d987121 + 249bbb9 commit bc61827

File tree

6 files changed

+958
-0
lines changed
  • LeetCode SQL 50 Solution

6 files changed

+958
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# 🎓 Find the Number of Times Each Student Attended Each Exam - LeetCode 1204
2+
3+
## 📌 Problem Statement
4+
You are given three tables: **Students**, **Subjects**, and **Examinations**, which contain information about students, subjects, and exam attendance.
5+
6+
### 📊 Students Table
7+
| Column Name | Type |
8+
| ------------ | ------- |
9+
| student_id | int |
10+
| student_name | varchar |
11+
- `student_id` is the **primary key**.
12+
- Each row represents a **unique student**.
13+
14+
### 📊 Subjects Table
15+
| Column Name | Type |
16+
| ------------ | ------- |
17+
| subject_name | varchar |
18+
- `subject_name` is the **primary key**.
19+
- Each row represents a **unique subject**.
20+
21+
### 📊 Examinations Table
22+
| Column Name | Type |
23+
| ------------ | ------- |
24+
| student_id | int |
25+
| subject_name | varchar |
26+
- **No primary key** (may contain duplicates).
27+
- Each row indicates that a student attended an exam for a specific subject.
28+
29+
### 🔢 Goal:
30+
Find the **number of times each student attended each exam**.
31+
If a student did **not attend an exam**, return `0`.
32+
Return the results **ordered by** `student_id` and `subject_name`.
33+
34+
---
35+
36+
## 📊 Example 1:
37+
### Input:
38+
39+
### **Students Table**
40+
| student_id | student_name |
41+
| ---------- | ------------ |
42+
| 1 | Alice |
43+
| 2 | Bob |
44+
| 13 | John |
45+
| 6 | Alex |
46+
47+
### **Subjects Table**
48+
| subject_name |
49+
| ------------ |
50+
| Math |
51+
| Physics |
52+
| Programming |
53+
54+
### **Examinations Table**
55+
| student_id | subject_name |
56+
| ---------- | ------------ |
57+
| 1 | Math |
58+
| 1 | Physics |
59+
| 1 | Programming |
60+
| 2 | Programming |
61+
| 1 | Physics |
62+
| 1 | Math |
63+
| 13 | Math |
64+
| 13 | Programming |
65+
| 13 | Physics |
66+
| 2 | Math |
67+
| 1 | Math |
68+
69+
### Output:
70+
| student_id | student_name | subject_name | attended_exams |
71+
| ---------- | ------------ | ------------ | -------------- |
72+
| 1 | Alice | Math | 3 |
73+
| 1 | Alice | Physics | 2 |
74+
| 1 | Alice | Programming | 1 |
75+
| 2 | Bob | Math | 1 |
76+
| 2 | Bob | Physics | 0 |
77+
| 2 | Bob | Programming | 1 |
78+
| 6 | Alex | Math | 0 |
79+
| 6 | Alex | Physics | 0 |
80+
| 6 | Alex | Programming | 0 |
81+
| 13 | John | Math | 1 |
82+
| 13 | John | Physics | 1 |
83+
| 13 | John | Programming | 1 |
84+
85+
---
86+
87+
## 🖥 SQL Solution
88+
89+
### 1️⃣ Standard MySQL Query
90+
#### **Explanation:**
91+
- **Use `CROSS JOIN`** to generate **all possible student-subject combinations**.
92+
- **Use `LEFT JOIN`** to attach attendance records from `Examinations`.
93+
- **Use `COUNT(e.subject_name)`** to count how many times a student attended an exam.
94+
- **Sort results by** `student_id` and `subject_name`.
95+
96+
```sql
97+
SELECT s.student_id, s.student_name, sb.subject_name,
98+
COUNT(e.subject_name) AS attended_exams
99+
FROM Students s
100+
CROSS JOIN Subjects sb
101+
LEFT JOIN Examinations e
102+
ON s.student_id = e.student_id AND sb.subject_name = e.subject_name
103+
GROUP BY s.student_id, sb.subject_name
104+
ORDER BY s.student_id, sb.subject_name;
105+
```
106+
107+
---
108+
109+
### 2️⃣ Alternative SQL Query (Using `COALESCE`)
110+
```sql
111+
SELECT s.student_id, s.student_name, sb.subject_name,
112+
COALESCE(COUNT(e.subject_name), 0) AS attended_exams
113+
FROM Students s
114+
CROSS JOIN Subjects sb
115+
LEFT JOIN Examinations e
116+
ON s.student_id = e.student_id AND sb.subject_name = e.subject_name
117+
GROUP BY s.student_id, sb.subject_name
118+
ORDER BY s.student_id, sb.subject_name;
119+
```
120+
- **Uses `COALESCE(COUNT(...), 0)`** to explicitly handle `NULL` values.
121+
122+
---
123+
124+
### 3️⃣ Alternative SQL Query (Using `WITH ROLLUP`)
125+
```sql
126+
SELECT s.student_id, s.student_name, sb.subject_name,
127+
COUNT(e.subject_name) AS attended_exams
128+
FROM Students s
129+
CROSS JOIN Subjects sb
130+
LEFT JOIN Examinations e
131+
ON s.student_id = e.student_id AND sb.subject_name = e.subject_name
132+
GROUP BY s.student_id, sb.subject_name WITH ROLLUP
133+
HAVING GROUPING(subject_name) = 0
134+
ORDER BY s.student_id, sb.subject_name;
135+
```
136+
- **Uses `WITH ROLLUP`** to generate **aggregated results**.
137+
138+
---
139+
140+
## 🐍 Pandas Solution (Python)
141+
#### **Explanation:**
142+
- **Generate all possible (student, subject) pairs** using `pd.merge()`.
143+
- **Group by student_id and subject_name**, then count occurrences.
144+
- **Fill missing values with `0`**.
145+
146+
```python
147+
import pandas as pd
148+
149+
def student_exam_attendance(students: pd.DataFrame, subjects: pd.DataFrame, exams: pd.DataFrame) -> pd.DataFrame:
150+
# Create all possible student-subject combinations
151+
all_combinations = students.merge(subjects, how="cross")
152+
153+
# Merge with exam data
154+
merged = all_combinations.merge(exams, on=["student_id", "subject_name"], how="left")
155+
156+
# Count the number of times each student attended each exam
157+
result = merged.groupby(["student_id", "student_name", "subject_name"]).size().reset_index(name="attended_exams")
158+
159+
return result.sort_values(["student_id", "subject_name"])
160+
```
161+
162+
---
163+
164+
## 📁 File Structure
165+
```
166+
📂 Student-Exam-Attendance
167+
│── 📜 README.md
168+
│── 📜 solution.sql
169+
│── 📜 solution_pandas.py
170+
│── 📜 test_cases.sql
171+
```
172+
173+
---
174+
175+
## 🔗 Useful Links
176+
- 📖 [LeetCode Problem](https://leetcode.com/problems/find-the-number-of-times-each-student-attended-each-exam/)
177+
- 📚 [SQL `CROSS JOIN` Documentation](https://www.w3schools.com/sql/sql_join_cross.asp)
178+
- 🐍 [Pandas Merge Documentation](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html)
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# 🍽️ Restaurant Growth - LeetCode 321
2+
3+
## 📌 Problem Statement
4+
You are given a table **Customer**, which records daily customer transactions in a restaurant.
5+
The restaurant owner wants to analyze a **7-day moving average** of customer spending.
6+
7+
### 📊 Customer Table
8+
| Column Name | Type |
9+
| ----------- | ------- |
10+
| customer_id | int |
11+
| name | varchar |
12+
| visited_on | date |
13+
| amount | int |
14+
- **(customer_id, visited_on) is the primary key**.
15+
- `visited_on` represents the date a customer visited the restaurant.
16+
- `amount` represents the total amount paid by a customer on that day.
17+
18+
---
19+
20+
## 🔢 Goal:
21+
Compute the **7-day moving average** of customer spending.
22+
- The window consists of **current day + 6 days before**.
23+
- `average_amount` should be **rounded to 2 decimal places**.
24+
- The result should be **ordered by `visited_on` in ascending order**.
25+
26+
---
27+
28+
## 📊 Example 1:
29+
### **Input:**
30+
#### **Customer Table**
31+
| customer_id | name | visited_on | amount |
32+
| ----------- | ------- | ---------- | ------ |
33+
| 1 | Jhon | 2019年01月01日 | 100 |
34+
| 2 | Daniel | 2019年01月02日 | 110 |
35+
| 3 | Jade | 2019年01月03日 | 120 |
36+
| 4 | Khaled | 2019年01月04日 | 130 |
37+
| 5 | Winston | 2019年01月05日 | 110 |
38+
| 6 | Elvis | 2019年01月06日 | 140 |
39+
| 7 | Anna | 2019年01月07日 | 150 |
40+
| 8 | Maria | 2019年01月08日 | 80 |
41+
| 9 | Jaze | 2019年01月09日 | 110 |
42+
| 1 | Jhon | 2019年01月10日 | 130 |
43+
| 3 | Jade | 2019年01月10日 | 150 |
44+
45+
### **Output:**
46+
| visited_on | amount | average_amount |
47+
| ---------- | ------ | -------------- |
48+
| 2019年01月07日 | 860 | 122.86 |
49+
| 2019年01月08日 | 840 | 120 |
50+
| 2019年01月09日 | 840 | 120 |
51+
| 2019年01月10日 | 1000 | 142.86 |
52+
53+
### **Explanation:**
54+
1. **First moving average (2019年01月01日 to 2019年01月07日)**
55+
\[
56+
(100 + 110 + 120 + 130 + 110 + 140 + 150) / 7 = 122.86
57+
\]
58+
2. **Second moving average (2019年01月02日 to 2019年01月08日)**
59+
\[
60+
(110 + 120 + 130 + 110 + 140 + 150 + 80) / 7 = 120
61+
\]
62+
3. **Third moving average (2019年01月03日 to 2019年01月09日)**
63+
\[
64+
(120 + 130 + 110 + 140 + 150 + 80 + 110) / 7 = 120
65+
\]
66+
4. **Fourth moving average (2019年01月04日 to 2019年01月10日)**
67+
\[
68+
(130 + 110 + 140 + 150 + 80 + 110 + 130 + 150) / 7 = 142.86
69+
\]
70+
71+
---
72+
73+
## 🖥 SQL Solutions
74+
75+
### 1️⃣ **Using `WINDOW FUNCTION` (`SUM() OVER` + `RANK() OVER`)**
76+
#### **Explanation:**
77+
- First, **group transactions per day** using `SUM(amount)`.
78+
- Then, use `SUM() OVER (ROWS 6 PRECEDING)` to calculate **moving sum** over 7 days.
79+
- Use `RANK()` to track row numbers and filter rows with `rk > 6`.
80+
- Finally, compute `ROUND(amount / 7, 2)`.
81+
82+
```sql
83+
WITH t AS (
84+
SELECT
85+
visited_on,
86+
SUM(amount) OVER (
87+
ORDER BY visited_on
88+
ROWS 6 PRECEDING
89+
) AS amount,
90+
RANK() OVER (
91+
ORDER BY visited_on
92+
ROWS 6 PRECEDING
93+
) AS rk
94+
FROM (
95+
SELECT visited_on, SUM(amount) AS amount
96+
FROM Customer
97+
GROUP BY visited_on
98+
) AS tt
99+
)
100+
SELECT visited_on, amount, ROUND(amount / 7, 2) AS average_amount
101+
FROM t
102+
WHERE rk > 6;
103+
```
104+
105+
---
106+
107+
### 2️⃣ **Using `JOIN` + `DATEDIFF()`**
108+
#### **Explanation:**
109+
- Use a **self-join** to find transactions **within a 7-day range**.
110+
- Sum the `amount` for each window and calculate the moving average.
111+
- Use `DATEDIFF(a.visited_on, b.visited_on) BETWEEN 0 AND 6` to filter records.
112+
- Ensure only complete 7-day windows are included.
113+
114+
```sql
115+
SELECT
116+
a.visited_on,
117+
SUM(b.amount) AS amount,
118+
ROUND(SUM(b.amount) / 7, 2) AS average_amount
119+
FROM
120+
(SELECT DISTINCT visited_on FROM customer) AS a
121+
JOIN customer AS b
122+
ON DATEDIFF(a.visited_on, b.visited_on) BETWEEN 0 AND 6
123+
WHERE
124+
a.visited_on >= (SELECT MIN(visited_on) FROM customer) + 6
125+
GROUP BY a.visited_on
126+
ORDER BY a.visited_on;
127+
```
128+
129+
---
130+
131+
## 🐍 Pandas Solution (Python)
132+
#### **Explanation:**
133+
- **Group by `visited_on`** and sum `amount` per day.
134+
- **Use `.rolling(7).sum()`** to compute the moving sum over 7 days.
135+
- **Drop NaN values** to exclude incomplete windows.
136+
- **Round the average to 2 decimal places**.
137+
138+
```python
139+
import pandas as pd
140+
141+
def restaurant_growth(customers: pd.DataFrame) -> pd.DataFrame:
142+
# Aggregate daily amounts
143+
daily_amount = customers.groupby("visited_on")["amount"].sum().reset_index()
144+
145+
# Compute rolling 7-day sum and moving average
146+
daily_amount["amount"] = daily_amount["amount"].rolling(7).sum()
147+
daily_amount["average_amount"] = (daily_amount["amount"] / 7).round(2)
148+
149+
# Drop incomplete windows
150+
daily_amount = daily_amount.dropna().reset_index(drop=True)
151+
152+
return daily_amount
153+
```
154+
155+
---
156+
157+
## 📁 File Structure
158+
```
159+
📂 Restaurant-Growth
160+
│── 📜 README.md
161+
│── 📜 solution.sql
162+
│── 📜 solution_pandas.py
163+
│── 📜 test_cases.sql
164+
```
165+
166+
---
167+
168+
## 🔗 Useful Links
169+
- 📖 [LeetCode Problem](https://leetcode.com/problems/restaurant-growth/)
170+
- 📚 [SQL `WINDOW FUNCTIONS` Documentation](https://www.w3schools.com/sql/sql_window.asp)
171+
- 🐍 [Pandas Rolling Window](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rolling.html)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /