Skip to content

Commit e83943b

Browse files
authored
feat: update solutions to lc problems (doocs#1799)
* No.1225.Report Contiguous Dates * No.1270.All People Report to the Given Manager * No.1412.Find the Quiet Students in All Exams * No.1596.The Most Frequently Ordered Products for Each Customer * No.1709.Biggest Window Between Visits * No.1767.Find the Subtasks That Did Not Execute
1 parent 242c377 commit e83943b

File tree

18 files changed

+234
-195
lines changed

18 files changed

+234
-195
lines changed

.prettierignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ node_modules/
1919
/solution/1600-1699/1613.Find the Missing IDs/Solution.sql
2020
/solution/1600-1699/1635.Hopper Company Queries I/Solution.sql
2121
/solution/1600-1699/1651.Hopper Company Queries III/Solution.sql
22-
/solution/1700-1799/1767.Find the Subtasks That Did Not Execute/Solution.sql
2322
/solution/1800-1899/1873.Calculate Special Bonus/Solution.sql
2423
/solution/2100-2199/2118.Build the Equation/Solution.sql
2524
/solution/2100-2199/2153.The Number of Passengers in Each Bus II/Solution.sql

solution/1200-1299/1225.Report Contiguous Dates/README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,28 @@ Succeeded table:
8787

8888
<!-- 这里可写通用的实现逻辑 -->
8989

90+
**方法一:合并 + 窗口函数 + 分组求最大最小值**
91+
92+
我们可以将两个表合并,用一个字段 $st$ 表示状态,其中 `failed` 表示失败,`succeeded` 表示成功。然后我们可以使用窗口函数,将相同状态的记录分到一组,求出每个日期与其所在组排名的差值 $pt$,作为同一个连续状态的标识。最后我们可以按照 $st$ 和 $pt$ 分组,求出每组的最小日期和最大日期,然后按照最小日期排序即可。
93+
9094
<!-- tabs:start -->
9195

9296
### **SQL**
9397

9498
```sql
9599
# Write your MySQL query statement below
100+
WITH
101+
T AS (
102+
SELECT fail_date AS dt, 'failed' AS st
103+
FROM Failed
104+
WHERE year(fail_date) = 2019
105+
UNION ALL
106+
SELECT success_date AS dt, 'succeeded' AS st
107+
FROM Succeeded
108+
WHERE year(success_date) = 2019
109+
)
96110
SELECT
97-
state AS period_state,
111+
st AS period_state,
98112
min(dt) AS start_date,
99113
max(dt) AS end_date
100114
FROM
@@ -104,27 +118,14 @@ FROM
104118
subdate(
105119
dt,
106120
rank() OVER (
107-
PARTITION BY state
121+
PARTITION BY st
108122
ORDER BY dt
109123
)
110-
) AS dif
111-
FROM
112-
(
113-
SELECT
114-
'failed' AS state,
115-
fail_date AS dt
116-
FROM failed
117-
WHERE fail_date BETWEEN '2019-01-01' AND '2019-12-31'
118-
UNION ALL
119-
SELECT
120-
'succeeded' AS state,
121-
success_date AS dt
122-
FROM succeeded
123-
WHERE success_date BETWEEN '2019-01-01' AND '2019-12-31'
124-
) AS t1
125-
) AS t2
126-
GROUP BY state, dif
127-
ORDER BY dt;
124+
) AS pt
125+
FROM T
126+
) AS t
127+
GROUP BY 1, pt
128+
ORDER BY 2;
128129
```
129130

130131
<!-- tabs:end -->

solution/1200-1299/1225.Report Contiguous Dates/README_EN.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,28 @@ From 2019-01-06 to 2019-01-06 all tasks succeeded and the system state was &quot
8484

8585
## Solutions
8686

87+
**Solution 1: Union + Window Function + Group By**
88+
89+
We can merge the two tables into one table with a field `st` representing the status, where `failed` indicates failure and `succeeded` indicates success. Then, we can use a window function to group the records with the same status into one group, and calculate the difference between each date and its rank within the group as `pt`, which serves as the identifier for the same continuous status. Finally, we can group by `st` and `pt`, and calculate the minimum and maximum dates for each group, and sort by the minimum date.
90+
8791
<!-- tabs:start -->
8892

8993
### **SQL**
9094

9195
```sql
9296
# Write your MySQL query statement below
97+
WITH
98+
T AS (
99+
SELECT fail_date AS dt, 'failed' AS st
100+
FROM Failed
101+
WHERE year(fail_date) = 2019
102+
UNION ALL
103+
SELECT success_date AS dt, 'succeeded' AS st
104+
FROM Succeeded
105+
WHERE year(success_date) = 2019
106+
)
93107
SELECT
94-
state AS period_state,
108+
st AS period_state,
95109
min(dt) AS start_date,
96110
max(dt) AS end_date
97111
FROM
@@ -101,27 +115,14 @@ FROM
101115
subdate(
102116
dt,
103117
rank() OVER (
104-
PARTITION BY state
118+
PARTITION BY st
105119
ORDER BY dt
106120
)
107-
) AS dif
108-
FROM
109-
(
110-
SELECT
111-
'failed' AS state,
112-
fail_date AS dt
113-
FROM failed
114-
WHERE fail_date BETWEEN '2019-01-01' AND '2019-12-31'
115-
UNION ALL
116-
SELECT
117-
'succeeded' AS state,
118-
success_date AS dt
119-
FROM succeeded
120-
WHERE success_date BETWEEN '2019-01-01' AND '2019-12-31'
121-
) AS t1
122-
) AS t2
123-
GROUP BY state, dif
124-
ORDER BY dt;
121+
) AS pt
122+
FROM T
123+
) AS t
124+
GROUP BY 1, pt
125+
ORDER BY 2;
125126
```
126127

127128
<!-- tabs:end -->
Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# Write your MySQL query statement below
2+
WITH
3+
T AS (
4+
SELECT fail_date AS dt, 'failed' AS st
5+
FROM Failed
6+
WHERE year(fail_date) = 2019
7+
UNION ALL
8+
SELECT success_date AS dt, 'succeeded' AS st
9+
FROM Succeeded
10+
WHERE year(success_date) = 2019
11+
)
212
SELECT
3-
state AS period_state,
13+
st AS period_state,
414
min(dt) AS start_date,
515
max(dt) AS end_date
616
FROM
@@ -10,24 +20,11 @@ FROM
1020
subdate(
1121
dt,
1222
rank() OVER (
13-
PARTITION BY state
23+
PARTITION BY st
1424
ORDER BY dt
1525
)
16-
) AS dif
17-
FROM
18-
(
19-
SELECT
20-
'failed' AS state,
21-
fail_date AS dt
22-
FROM failed
23-
WHERE fail_date BETWEEN '2019-01-01' AND '2019-12-31'
24-
UNION ALL
25-
SELECT
26-
'succeeded' AS state,
27-
success_date AS dt
28-
FROM succeeded
29-
WHERE success_date BETWEEN '2019-01-01' AND '2019-12-31'
30-
) AS t1
31-
) AS t2
32-
GROUP BY state, dif
33-
ORDER BY dt;
26+
) AS pt
27+
FROM T
28+
) AS t
29+
GROUP BY 1, pt
30+
ORDER BY 2;

solution/1200-1299/1270.All People Report to the Given Manager/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ employee_id 是 3, 8 ,9 的职员不会直接或间接的汇报给公司 CEO
7171

7272
<!-- 这里可写通用的实现逻辑 -->
7373

74+
**方法一:两次连接**
75+
76+
我们可以通过两次连接来找到所有直接或间接向公司 CEO 汇报工作的职工的 `employee_id`
77+
78+
具体地,我们首先通过一次连接,找到每个 `manager_id` 对应的上级经理的 `manager_id`,然后再通过一次连接,找到更上一级经理的 `manager_id`,最后,如果更上一级的 `manager_id` 为 $1$,且员工的 `employee_id` 不为 $1$,则说明该员工直接或间接向公司 CEO 汇报工作。
79+
7480
<!-- tabs:start -->
7581

7682
### **SQL**

solution/1200-1299/1270.All People Report to the Given Manager/README_EN.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,17 @@ The employees with employee_id 3, 8, and 9 do not report their work to the head
6666

6767
## Solutions
6868

69+
**Solution 1: Two Joins**
70+
71+
We can use two joins to find all employees who report directly or indirectly to the company CEO.
72+
73+
Specifically, we first use a join to find the `manager_id` of the superior manager for each `manager_id`, and then use another join to find the `manager_id` of the higher-level manager. Finally, if the `manager_id` of the higher-level manager is $1$ and the `employee_id` of the employee is not $1$, it means that the employee reports directly or indirectly to the company CEO.
74+
6975
<!-- tabs:start -->
7076

7177
### **SQL**
7278

7379
```sql
74-
# Write your MySQL query statement below
75-
7680
# Write your MySQL query statement below
7781
SELECT e1.employee_id
7882
FROM

solution/1400-1499/1412.Find the Quiet Students in All Exams/README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,34 +93,39 @@ Exam 表:
9393

9494
<!-- 这里可写通用的实现逻辑 -->
9595

96+
**方法一:使用 RANK() 窗口函数 + 分组聚合**
97+
98+
我们可以使用 `RANK()` 窗口函数来计算每个学生在每场考试中的正序排名 $rk1$ 和倒序排序 $rk2$,得到表 $T$。
99+
100+
接下来,我们将表 $T$ 与表 $Student$ 进行内连接,然后按照学生编号进行分组聚合,得到每个学生在所有考试中的正序排名为 $1$ 的次数 $cnt1$ 和倒序排名为 $1$ 的次数 $cnt2$。如果 $cnt1$ 和 $cnt2$ 都为 $0$,则说明该学生在所有考试中都处于中游。
101+
96102
<!-- tabs:start -->
97103

98104
### **SQL**
99105

100106
```sql
101107
# Write your MySQL query statement below
102108
WITH
103-
t AS (
109+
T AS (
104110
SELECT
105-
*,
111+
student_id,
106112
rank() OVER (
107113
PARTITION BY exam_id
108-
ORDER BY score DESC
114+
ORDER BY score
109115
) AS rk1,
110116
rank() OVER (
111117
PARTITION BY exam_id
112-
ORDER BY score ASC
118+
ORDER BY score DESC
113119
) AS rk2
114120
FROM Exam
115121
)
116-
SELECT
117-
t.student_id,
118-
student_name
122+
SELECT student_id, student_name
119123
FROM
120-
t
121-
JOIN Student AS s ON t.student_id = s.student_id
122-
GROUP BY t.student_id
123-
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0;
124+
T
125+
JOIN Student USING (student_id)
126+
GROUP BY 1
127+
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0
128+
ORDER BY 1;
124129
```
125130

126131
<!-- tabs:end -->

solution/1400-1499/1412.Find the Quiet Students in All Exams/README_EN.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,34 +89,39 @@ So, we only return the information of Student 2.
8989

9090
## Solutions
9191

92+
**Solution 1: Using RANK() Window Function + Group By**
93+
94+
We can use the `RANK()` window function to calculate the ascending rank $rk1$ and descending rank $rk2$ of each student in each exam, and obtain the table $T$.
95+
96+
Next, we can perform an inner join between the table $T$ and the table $Student$, and then group by student ID to obtain the number of times each student has a rank of $1$ in ascending order $cnt1$ and descending order $cnt2$ in all exams. If both $cnt1$ and $cnt2$ are $0$, it means that the student is in the middle of the pack in all exams.
97+
9298
<!-- tabs:start -->
9399

94100
### **SQL**
95101

96102
```sql
97103
# Write your MySQL query statement below
98104
WITH
99-
t AS (
105+
T AS (
100106
SELECT
101-
*,
107+
student_id,
102108
rank() OVER (
103109
PARTITION BY exam_id
104-
ORDER BY score DESC
110+
ORDER BY score
105111
) AS rk1,
106112
rank() OVER (
107113
PARTITION BY exam_id
108-
ORDER BY score ASC
114+
ORDER BY score DESC
109115
) AS rk2
110116
FROM Exam
111117
)
112-
SELECT
113-
t.student_id,
114-
student_name
118+
SELECT student_id, student_name
115119
FROM
116-
t
117-
JOIN Student AS s ON t.student_id = s.student_id
118-
GROUP BY t.student_id
119-
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0;
120+
T
121+
JOIN Student USING (student_id)
122+
GROUP BY 1
123+
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0
124+
ORDER BY 1;
120125
```
121126

122127
<!-- tabs:end -->
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
# Write your MySQL query statement below
22
WITH
3-
t AS (
3+
T AS (
44
SELECT
5-
*,
5+
student_id,
66
rank() OVER (
77
PARTITION BY exam_id
8-
ORDER BY score DESC
8+
ORDER BY score
99
) AS rk1,
1010
rank() OVER (
1111
PARTITION BY exam_id
12-
ORDER BY score ASC
12+
ORDER BY score DESC
1313
) AS rk2
1414
FROM Exam
1515
)
16-
SELECT
17-
t.student_id,
18-
student_name
16+
SELECT student_id, student_name
1917
FROM
20-
t
21-
JOIN Student AS s ON t.student_id = s.student_id
22-
GROUP BY t.student_id
23-
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0;
18+
T
19+
JOIN Student USING (student_id)
20+
GROUP BY 1
21+
HAVING sum(rk1 = 1) = 0 AND sum(rk2 = 1) = 0
22+
ORDER BY 1;

solution/1500-1599/1596.The Most Frequently Ordered Products for Each Customer/README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ John (customer 5) 没有订购过商品, 所以我们并没有把 John 包含在
124124

125125
<!-- 这里可写通用的实现逻辑 -->
126126

127+
**方法一:分组 + 窗口函数**
128+
129+
我们将 `Orders` 表按照 `customer_id``product_id` 进行分组,然后利用窗口函数 `rank()`,按照 `customer_id` 分区,并且按照 `count(1)` 降序排列,得到每个 `customer_id` 下对应的 `product_id` 的排名,排名为 $1$ 的就是该 `customer_id` 下最经常订购的商品。
130+
127131
<!-- tabs:start -->
128132

129133
### **SQL**
@@ -132,12 +136,8 @@ John (customer 5) 没有订购过商品, 所以我们并没有把 John 包含在
132136

133137
```sql
134138
# Write your MySQL query statement below
135-
SELECT
136-
customer_id,
137-
p.product_id,
138-
p.product_name
139-
FROM
140-
(
139+
WITH
140+
T AS (
141141
SELECT
142142
customer_id,
143143
product_id,
@@ -146,9 +146,12 @@ FROM
146146
ORDER BY count(1) DESC
147147
) AS rk
148148
FROM Orders
149-
GROUP BY customer_id, product_id
150-
) AS o
151-
JOIN Products AS p ON o.product_id = p.product_id
149+
GROUP BY 1, 2
150+
)
151+
SELECT customer_id, product_id, product_name
152+
FROM
153+
T
154+
JOIN Products USING (product_id)
152155
WHERE rk = 1;
153156
```
154157

0 commit comments

Comments
 (0)