高级农民
- 积分
- 4142
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2017-1-22
- 最后登录
- 1970-1-1
|
601. Human Traffic of Stadium
Hard
Topics
conpanies icon
Companies
SQL Schema
Pandas Schema
Table: Stadium
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| id | int |
| visit_date | date |
| people | int |
+---------------+---------+
visit_date is the column with unique values for this table.
Each row of this table contains the visit date and visit id to the stadium with the number of people during the visit.
As the id increases, the date increases as well.
Write a solution to display the records with three or more rows with consecutive id's, and the number of people is greater than or equal to 100 for each.
Return the result table ordered by visit_date in ascending order.
The result format is in the following example.
Example 1:
Input:
Stadium table:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 1 | 2017-01-01 | 10 |
| 2 | 2017-01-02 | 109 |
| 3 | 2017-01-03 | 150 |
| 4 | 2017-01-04 | 99 |
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-09 | 188 |
+------+------------+-----------+
Output:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-09 | 188 |
+------+------------+-----------+
Explanation:
The four rows with ids 5, 6, 7, and 8 have consecutive ids and each of them has >= 100 people attended. Note that row 8 was included even though the visit_date was not the next day after row 7.
The rows with ids 2 and 3 are not included because we need at least three consecutive ids.
这道 601. Human Traffic of Stadium 是一道非常经典的 Hard SQL。
它和你刚刚做的 603 有直接关系:都是找 consecutive rows,但 601 更难,因为:
不是找“相邻的一对”,而是找出属于连续 ≥ 3 个满足条件的区间里的所有行。
1. 先抓住最重要的条件
题目要求每一行满足:
people >= 100
然后这些行还必须有:
连续的 id
并且连续长度至少是:
3
注意:
连续的是 id,不是 visit_date。
例如:
id=7 → 2017-01-07
id=8 → 2017-01-09
虽然日期跳了一天,但:
7, 8
仍然是连续 id。
2. 最容易想到但不完整的方法
首先把 people < 100 去掉:
SELECT *
FROM Stadium
WHERE people >= 100;
例子变成:
id people
2 109
3 150
5 145
6 1455
7 199
8 188
现在需要找到:
2,3 ❌ 只有2个
5,6,7,8 ✅ 有4个
所以最终返回:
5
6
7
8
用 LAG / LEAD:我更推荐这个- SELECT id, visit_date, people
- FROM (
- SELECT
- *,
- LAG(id, 1) OVER (ORDER BY id) AS prev_id,
- LAG(id, 2) OVER (ORDER BY id) AS prev2_id,
- LEAD(id, 1) OVER (ORDER BY id) AS next_id,
- LEAD(id, 2) OVER (ORDER BY id) AS next2_id
- FROM Stadium
- WHERE people >= 100
- ) t
- WHERE
- (prev_id = id - 1 AND prev2_id = id - 2)
- OR (prev_id = id - 1 AND next_id = id + 1)
- OR (next_id = id + 1 AND next2_id = id + 2)
- ORDER BY visit_date;
复制代码 为什么需要三个条件?
我们现在只保留:
people >= 100
假设得到:
id
--
2
3
5
6
7
8
对于 5:
prev2 = 3
prev = 2
id = 5
不连续。
但是:
5 → 6 → 7
所以 5 应该被保留。
于是我们需要检查三种情况。
情况 1:当前行是连续区间的第三个或之后
id-2, id-1, id
对应:
prev2_id = id - 2
AND prev_id = id - 1
例如:
5, 6, 7
↑
当前
7 可以被找到。
情况 2:当前行在连续区间中间
id-1, id, id+1
对应:
prev_id = id - 1
AND next_id = id + 1
例如:
5, 6, 7
↑
当前
6 可以被找到。
情况 3:当前行是连续区间的第一个或之前
id, id+1, id+2
对应:
next_id = id + 1
AND next2_id = id + 2
例如:
5, 6, 7
↑
当前
5 可以被找到。
所以:
WHERE
(prev_id = id - 1 AND prev2_id = id - 2)
OR (prev_id = id - 1 AND next_id = id + 1)
OR (next_id = id + 1 AND next2_id = id + 2)
本质就是:
当前行前后至少能找到两个连续的、高客流记录。 |
|