SQL每日刷题—lead()窗口

题目

编写一个 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

你可能感兴趣的:(SQL,sql,mysql)