Skip to content

Commit cc99c13

Browse files
authored
feat: add sql solutions to lc problems (doocs#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

Lines changed: 15 additions & 15 deletions
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

Lines changed: 15 additions & 15 deletions
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

Lines changed: 4 additions & 6 deletions
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 9 additions & 1 deletion
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

Lines changed: 9 additions & 1 deletion
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
```
Lines changed: 8 additions & 9 deletions
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

Lines changed: 1 addition & 1 deletion
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

0 commit comments

Comments
 (0)