SQL中有查询序列的成语吗?

Is there an idiom for querying sequences in SQL?

我正在学习面试一份涉及很多 SQL 的工作。我注意到一些练习围绕基于跨行序列的返回值展开,我很想知道是否有执行此操作的标准方法。我发现类似于下面的子查询的东西对于选择 max/min 值很有用:

( SELECT column FROM table ... ORDER BY column [DESC] LIMIT 1 )

这是来自 LeetCode 的相关示例:

Table: Stadium

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| visit_date    | date    |
| people        | int     |
+---------------+---------+
visit_date is the primary key 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. No two rows will have the same visit_date, and as the id increases, the dates increase as well.

Write an SQL query 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.

查询结果格式如下例

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       |
+------+------------+-----------+

我尝试使用用户变量来解决问题。下面的代码是我最好的解决方案:

SET @rowIndex = 0;

SELECT s1.id, s1.visit_date, s1.people
FROM ( SELECT @rowIndex:=@rowIndex+1 as rowIndex, s.id, s.visit_date, s.people
    FROM Stadium as s
    WHERE s.people >=100 ) as s1
GROUP BY rowIndex - s1.id, s1.id, s1.visit_date, s1.people
HAVING COUNT(s.id) >= 3
ORDER BY s1.visit_date

上面的查询某处有语法错误。消息:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT s1.id, s1.visit_date, s1.people FROM ( SELECT @rowIndex := @rowIndex+1 as' at line 4

有没有人最喜欢根据序列选择行的方法?也许不太重要,有人能发现我上面的查询中的错误吗?

我会把它作为一个 gaps-and-island 问题来解决。这是使用 window 函数的方法:

select id, visit_date, people
from (
    select s.*, count(*) over(partition by id - rn) cnt
    from (
        select s.*, row_number() over(order by id) rn
        from stadium s
        where people > 100
    ) s
) s
where cnt >= 3

思路是过滤掉访问次数少于100次的天数,然后利用 id的差值和单调递增的排名来识别孤岛(访问次数连续超过100次的天数)。然后我们可以只保留超过 3 行的组。