Skip to content

Commit cc99c13

Browse files
authored
feat: add sql solutions to lc problems (#1839)
* No.0550.Game Play Analysis IV * No.0596.Classes More Than 5 Students * No.0619.Biggest Single Number * No.1045.Customers Who Bought All Products * No.1729.Find Followers Count * No.1731.The Number of Employees Which Report to Each Employee * No.1789.Primary Department for Each Employee
1 parent ca25fb0 commit cc99c13

File tree

20 files changed

+120
-76
lines changed

20 files changed

+120
-76
lines changed

solution/0500-0599/0550.Game Play Analysis IV/README.md

+15-15
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ Activity table:
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

61+
**方法一:分组取最小值 + 左连接**
62+
63+
我们可以先找到每个玩家的首次登录日期,然后与原表进行左连接,连接条件为玩家 ID 相同且日期差为 $-1$,即第二天登录。那么,我们只需要统计出第二天登录的玩家数量中,玩家不为空的比率即可。
64+
65+
**方法二:窗口函数**
66+
67+
我们也可以使用窗口函数 `LEAD` 获取每个玩家的下一次登录日期,如果下一次登录日期与当前登录日期相差 $1$ 天,则说明该玩家在第二天登录,我们用一个字段 $st$ 记录该信息。然后,我们用窗口函数 `RANK` 对玩家 ID 按照日期升序排列,得到每个玩家的登录排名。最后,我们只需要统计出排名为 $1$ 的玩家中,字段 $st$ 不为空的比率即可。
68+
6169
<!-- tabs:start -->
6270

6371
### **SQL**
@@ -67,13 +75,11 @@ Activity table:
6775
SELECT ROUND(AVG(b.event_date IS NOT NULL), 2) AS fraction
6876
FROM
6977
(
70-
SELECT
71-
player_id,
72-
MIN(event_date) AS event_date
73-
FROM activity
74-
GROUP BY player_id
78+
SELECT player_id, MIN(event_date) AS event_date
79+
FROM Activity
80+
GROUP BY 1
7581
) AS a
76-
LEFT JOIN activity AS b
82+
LEFT JOIN Activity AS b
7783
ON a.player_id = b.player_id AND DATEDIFF(a.event_date, b.event_date) = -1;
7884
```
7985

@@ -89,20 +95,14 @@ WITH
8995
ORDER BY event_date
9096
),
9197
event_date
92-
) AS diff,
93-
ROW_NUMBER() OVER (
98+
) = 1 AS st,
99+
RANK() OVER (
94100
PARTITION BY player_id
95101
ORDER BY event_date
96102
) AS rk
97103
FROM Activity
98104
)
99-
SELECT
100-
ROUND(
101-
COUNT(DISTINCT IF(diff = 1, player_id, NULL)) / COUNT(
102-
DISTINCT player_id
103-
),
104-
2
105-
) AS fraction
105+
SELECT ROUND(COUNT(IF(st = 1, player_id, NULL)) / COUNT(DISTINCT player_id), 2) AS fraction
106106
FROM T
107107
WHERE rk = 1;
108108
```

solution/0500-0599/0550.Game Play Analysis IV/README_EN.md

+15-15
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ Only the player with id 1 logged back in after the first day he had logged in so
5353

5454
## Solutions
5555

56+
**Solution 1: Grouping and Minimum Value + Left Join**
57+
58+
We can first find the first login date of each player, and then perform a left join with the original table, with the join condition being that the player ID is the same and the date difference is $-1$, which means the player logged in on the second day. Then, we only need to calculate the ratio of non-null players among the players who logged in on the second day.
59+
60+
**Solution 2: Window Function**
61+
62+
We can use the `LEAD` window function to get the next login date of each player. If the next login date is one day after the current login date, it means that the player logged in on the second day, and we use a field $st$ to record this information. Then, we use the `RANK` window function to rank the player IDs in ascending order by date, and get the login ranking of each player. Finally, we only need to calculate the ratio of non-null $st$ values among the players with a ranking of $1$.
63+
5664
<!-- tabs:start -->
5765

5866
### **SQL**
@@ -62,13 +70,11 @@ Only the player with id 1 logged back in after the first day he had logged in so
6270
SELECT ROUND(AVG(b.event_date IS NOT NULL), 2) AS fraction
6371
FROM
6472
(
65-
SELECT
66-
player_id,
67-
MIN(event_date) AS event_date
68-
FROM activity
69-
GROUP BY player_id
73+
SELECT player_id, MIN(event_date) AS event_date
74+
FROM Activity
75+
GROUP BY 1
7076
) AS a
71-
LEFT JOIN activity AS b
77+
LEFT JOIN Activity AS b
7278
ON a.player_id = b.player_id AND DATEDIFF(a.event_date, b.event_date) = -1;
7379
```
7480

@@ -84,20 +90,14 @@ WITH
8490
ORDER BY event_date
8591
),
8692
event_date
87-
) AS diff,
88-
ROW_NUMBER() OVER (
93+
) = 1 AS st,
94+
RANK() OVER (
8995
PARTITION BY player_id
9096
ORDER BY event_date
9197
) AS rk
9298
FROM Activity
9399
)
94-
SELECT
95-
ROUND(
96-
COUNT(DISTINCT IF(diff = 1, player_id, NULL)) / COUNT(
97-
DISTINCT player_id
98-
),
99-
2
100-
) AS fraction
100+
SELECT ROUND(COUNT(IF(st = 1, player_id, NULL)) / COUNT(DISTINCT player_id), 2) AS fraction
101101
FROM T
102102
WHERE rk = 1;
103103
```

solution/0500-0599/0550.Game Play Analysis IV/Solution.sql

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
SELECT ROUND(AVG(b.event_date IS NOT NULL), 2) AS fraction
33
FROM
44
(
5-
SELECT
6-
player_id,
7-
MIN(event_date) AS event_date
8-
FROM activity
9-
GROUP BY player_id
5+
SELECT player_id, MIN(event_date) AS event_date
6+
FROM Activity
7+
GROUP BY 1
108
) AS a
11-
LEFT JOIN activity AS b
9+
LEFT JOIN Activity AS b
1210
ON a.player_id = b.player_id AND DATEDIFF(a.event_date, b.event_date) = -1;

solution/0500-0599/0596.Classes More Than 5 Students/README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ Courses table:
6363

6464
<!-- 这里可写通用的实现逻辑 -->
6565

66+
**方法一:分组统计**
67+
68+
我们可以使用 `GROUP BY` 语句,按照班级分组,然后使用 `HAVING` 语句,筛选出学生数量大于等于 $5$ 的班级。
69+
6670
<!-- tabs:start -->
6771

6872
### **SQL**
@@ -71,7 +75,7 @@ Courses table:
7175
# Write your MySQL query statement below
7276
SELECT class
7377
FROM Courses
74-
GROUP BY class
78+
GROUP BY 1
7579
HAVING COUNT(1) >= 5;
7680
```
7781

solution/0500-0599/0596.Classes More Than 5 Students/README_EN.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ Courses table:
5959

6060
## Solutions
6161

62+
**Solution 1: Grouping and Aggregation**
63+
64+
We can use the `GROUP BY` statement to group by class and then use the `HAVING` statement to filter out the classes with a student count greater than or equal to $5$.
65+
6266
<!-- tabs:start -->
6367

6468
### **SQL**
@@ -67,7 +71,7 @@ Courses table:
6771
# Write your MySQL query statement below
6872
SELECT class
6973
FROM Courses
70-
GROUP BY class
74+
GROUP BY 1
7175
HAVING COUNT(1) >= 5;
7276
```
7377

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Write your MySQL query statement below
22
SELECT class
33
FROM Courses
4-
GROUP BY class
4+
GROUP BY 1
55
HAVING COUNT(1) >= 5;

solution/0600-0699/0619.Biggest Single Number/README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ MyNumbers table:
9191

9292
<!-- 这里可写通用的实现逻辑 -->
9393

94+
**方法一:分组 + 子查询**
95+
96+
我们可以先将 `MyNumbers` 表按照 `num` 进行分组统计,找出只出现一次的数字,然后使用子查询找出最大的数字即可。
97+
98+
**方法二:分组 + `CASE` 表达式**
99+
100+
与方法一类似,我们可以先将 `MyNumbers` 表按照 `num` 进行分组统计,然后使用 `CASE` 表达式,找出只出现一次的数字,然后按数字降序排序,取第一个即可。
101+
94102
<!-- tabs:start -->
95103

96104
### **SQL**
@@ -102,7 +110,7 @@ FROM
102110
(
103111
SELECT num
104112
FROM MyNumbers
105-
GROUP BY num
113+
GROUP BY 1
106114
HAVING COUNT(1) = 1
107115
) AS t;
108116
```

solution/0600-0699/0619.Biggest Single Number/README_EN.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ MyNumbers table:
7979

8080
## Solutions
8181

82+
**Solution 1: Grouping and Subquery**
83+
84+
We can first group the `MyNumbers` table by `num` and count the number of occurrences of each number. Then, we can use a subquery to find the maximum number among the numbers that appear only once.
85+
86+
**Solution 2: Grouping and `CASE` Expression**
87+
88+
Similar to Method 1, we can first group the `MyNumbers` table by `num` and count the number of occurrences of each number. Then, we can use a `CASE` expression to find the numbers that appear only once, sort them in descending order by number, and take the first one.
89+
8290
<!-- tabs:start -->
8391

8492
### **SQL**
@@ -90,7 +98,7 @@ FROM
9098
(
9199
SELECT num
92100
FROM MyNumbers
93-
GROUP BY num
101+
GROUP BY 1
94102
HAVING COUNT(1) = 1
95103
) AS t;
96104
```
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# Write your MySQL query statement below
2-
SELECT
3-
CASE
4-
WHEN COUNT(1) = 1 THEN num
5-
ELSE NULL
6-
END AS num
7-
FROM MyNumbers
8-
GROUP BY num
9-
ORDER BY 1 DESC
10-
LIMIT 1;
2+
SELECT MAX(num) AS num
3+
FROM
4+
(
5+
SELECT num
6+
FROM MyNumbers
7+
GROUP BY 1
8+
HAVING COUNT(1) = 1
9+
) AS t;

solution/1000-1099/1045.Customers Who Bought All Products/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Product 表:
7777

7878
<!-- 这里可写通用的实现逻辑 -->
7979

80-
**方法一:GROUP BY + HAVING**
80+
**方法一:分组统计 + 子查询**
8181

8282
我们将 `Customer` 表按照 `customer_id` 进行分组,然后使用 `HAVING` 子句筛选出购买了所有产品的客户。
8383

solution/1000-1099/1045.Customers Who Bought All Products/README_EN.md

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ The customers who bought all the products (5 and 6) are customers with IDs 1 and
7474

7575
## Solutions
7676

77+
**Solution 1: Grouping and Subquery**
78+
79+
We can group the `Customer` table by `customer_id`, and then use the `HAVING` clause to filter out the customers who have not purchased all products. To do this, we can use a subquery to find the total number of distinct products, and then compare it with the number of distinct products purchased by each customer.
80+
7781
<!-- tabs:start -->
7882

7983
### **SQL**

solution/1700-1799/1729.Find Followers Count/README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,20 @@ Followers 表:
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

61-
`GROUP BY` 实现。
61+
**方法一:分组统计**
62+
63+
我们可以直接对 `Followers` 表按照 `user_id` 进行分组,然后使用 `COUNT` 函数统计每个用户的关注者数量即可。
6264

6365
<!-- tabs:start -->
6466

6567
### **SQL**
6668

6769
```sql
68-
SELECT
69-
user_id,
70-
COUNT(1) AS followers_count
70+
# Write your MySQL query statement below
71+
SELECT user_id, COUNT(1) AS followers_count
7172
FROM Followers
72-
GROUP BY user_id
73-
ORDER BY user_id;
73+
GROUP BY 1
74+
ORDER BY 1;
7475
```
7576

7677
<!-- tabs:end -->

solution/1700-1799/1729.Find Followers Count/README_EN.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,20 @@ The followers of 2 are {0,1}
5454

5555
## Solutions
5656

57+
**Solution 1: Grouping and Aggregation**
58+
59+
We can directly group the `Followers` table by `user_id`, and use the `COUNT` function to count the number of followers for each user.
60+
5761
<!-- tabs:start -->
5862

5963
### **SQL**
6064

6165
```sql
62-
SELECT
63-
user_id,
64-
COUNT(1) AS followers_count
66+
# Write your MySQL query statement below
67+
SELECT user_id, COUNT(1) AS followers_count
6568
FROM Followers
66-
GROUP BY user_id
67-
ORDER BY user_id;
69+
GROUP BY 1
70+
ORDER BY 1;
6871
```
6972

7073
<!-- tabs:end -->
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
SELECT
2-
user_id,
3-
COUNT(1) AS followers_count
1+
# Write your MySQL query statement below
2+
SELECT user_id, COUNT(1) AS followers_count
43
FROM Followers
5-
GROUP BY user_id
6-
ORDER BY user_id;
4+
GROUP BY 1
5+
ORDER BY 1;

solution/1700-1799/1731.The Number of Employees Which Report to Each Employee/README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ Hercy 有两个需要向他汇报的员工, 他们是 Alice and Bob. 他们的
5555

5656
<!-- 这里可写通用的实现逻辑 -->
5757

58+
**方法一:自连接 + 分组统计**
59+
60+
我们可以通过自连接的方式,将每个员工的上级经理信息连接到每个员工的信息上,然后再通过分组统计的方式,统计每个经理的下属员工数量和平均年龄。
61+
5862
<!-- tabs:start -->
5963

6064
### **SQL**
@@ -69,8 +73,8 @@ SELECT
6973
FROM
7074
Employees AS e1
7175
JOIN Employees AS e2 ON e1.reports_to = e2.employee_id
72-
GROUP BY e2.employee_id
73-
ORDER BY e2.employee_id;
76+
GROUP BY 1
77+
ORDER BY 1;
7478
```
7579

7680
<!-- tabs:end -->

solution/1700-1799/1731.The Number of Employees Which Report to Each Employee/README_EN.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ Employees table:
5454

5555
## Solutions
5656

57+
**Solution 1: Self-Join + Grouping**
58+
59+
We can use self-join to connect the information of each employee's superior manager to the information of each employee, and then use grouping and aggregation to count the number of subordinates and the average age of each manager.
60+
5761
<!-- tabs:start -->
5862

5963
### **SQL**
@@ -68,8 +72,8 @@ SELECT
6872
FROM
6973
Employees AS e1
7074
JOIN Employees AS e2 ON e1.reports_to = e2.employee_id
71-
GROUP BY e2.employee_id
72-
ORDER BY e2.employee_id;
75+
GROUP BY 1
76+
ORDER BY 1;
7377
```
7478

7579
<!-- tabs:end -->

solution/1700-1799/1731.The Number of Employees Which Report to Each Employee/Solution.sql

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ SELECT
77
FROM
88
Employees AS e1
99
JOIN Employees AS e2 ON e1.reports_to = e2.employee_id
10-
GROUP BY e2.employee_id
11-
ORDER BY e2.employee_id;
10+
GROUP BY 1
11+
ORDER BY 1;

solution/1700-1799/1789.Primary Department for Each Employee/README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ Employee table:
7171

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

74+
**方法一:合并**
75+
76+
我们可以查出所有已经有直属部门的员工,然后再查出所有只属于一个部门的员工,最后我们可以使用 `UNION` 合并两个结果集。
77+
7478
<!-- tabs:start -->
7579

7680
### **SQL**
@@ -85,7 +89,7 @@ WHERE primary_flag = 'Y'
8589
UNION
8690
SELECT employee_id, department_id
8791
FROM Employee
88-
GROUP BY employee_id
92+
GROUP BY 1
8993
HAVING COUNT(1) = 1;
9094
```
9195

0 commit comments

Comments
 (0)