题目
编写一个 SQL 查询以找出每行的人数大于或等于 100 且 id 连续的三行或更多行记录。
返回按 visit_date 升序排列的结果表。
查询结果格式如下所示。
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 |
+------+------------+-----------+
Result table:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-09 | 188 |
+------+------------+-----------+
id 为 5、6、7、8 的四行 id 连续,并且每行都有 >= 100 的人数记录。
请注意,即使第 7 行和第 8 行的 visit_date 不是连续的,输出也应当包含第 8 行,因为我们只需要考虑 id 连续的记录。
不输出 id 为 2 和 3 的行,因为至少需要三条 id 连续的记录。
预备知识
窗口函数lead()、lag()
同一次查询中取出同一字段的前N行的数据(Lag)和后N行的数据(Lead)作为独立的列。
lag(exp_str,offset,defval) over(partion by ..order by …)
lead(exp_str,offset,defval) over(partion by ..order by …)
- exp_str是字段名
- Offset是偏移量,即是上1个或上N个的值,假设当前行在表中排在第5行,则offset 为3,则表示我们所要找的数据行就是表中的第2行(即5-3=2)。
思路
1. 3表自连接,首先同时筛选出people>=100的记录,三表中Id依次相差1的即为相邻记录
2. lead()窗口函数向前取1、2行的记录,如果这三条记录都满足people>100即为相邻记录
代码
select distinct a.* from stadium a,stadium b,stadium c
where a.people>=100 and b.people>=100 and c.people>=100
and (
(a.id = b.id-1 and b.id = c.id -1) or
(a.id = b.id-1 and a.id = c.id +1) or
(a.id = b.id+1 and b.id = c.id +1)
) order by a.id
select distinct t2.*
from(
select *,
lead(people,1)over(order by visit_date ) as p2,
lead(people,2)over(order by visit_date ) as p3
from Stadium
)as t, Stadium as t2
where t.people >=100 and p2>=100 and p3>=100
and t2.id>=t.id and t2.id-2<=t.id
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/human-traffic-of-stadium