首页 > 解决方案 > 这个 WITH 子句的语法错误在哪里?

问题描述

我正在 LeetCode 上尝试这个问题。该界面引发了语法错误,但对于我来说,我无法弄清楚。这是问题:

表:体育场

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| visit_date    | date    |
| people        | int     |
+---------------+---------+

visit_date 是该表的主键。该表的每一行都包含访问日期和访问体育场的 ID 以及访问期间的人数。没有两行会有相同的 visit_date,并且随着 id 的增加,日期也会增加。

编写一条SQL查询,显示三行或三行以上id连续的记录,且每人人数大于等于100人。

返回按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 人参加。请注意,即使 visit_date 不是第 7 行之后的第二天,也包含第 8 行。id 为 2 和 3 的行不包括在内,因为我们需要至少三个连续的 id。

这是一个数据(注意:我仍在试图弄清楚如何插入日期,所以我将日期保存为字符串)。

谁能在下面的查询中发现语法错误?

# Write your MySQL query statement below
SET @rowIndex := 0;

WITH s1 as (
    SELECT @rowIndex := @rowIndex + 1 as rowIndex, s.*
    FROM Stadium as s
    WHERE s.people >= 100
    GROUP BY s.id
)

SELECT s2.id, s2.visit_date, s2.people
FROM s1 as s2
GROUP BY s2.rowIndex - s2.id, s2.id, s2.visit_date, s2.people
ORDER BY s2.visit_date

错误信息:

您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 4 行的 'WITH s1 (rowIndex, id, visit_date, people) as (SELECT @rowIndex := @rowInde' 附近使用正确的语法

另外,LeetCode 接口使用 MySQL v8.0,所以我认为这不是问题。

我使用下面的查询作为参考。(原创。)

SET @rowIndex := -1;
SELECT ROUND(AVG(t.LAT_N), 4) FROM
(
SELECT @rowIndex := @rowIndex+1 AS rowIndex, s.LAT_N FROM STATION AS s ORDER BY s.LAT_N
) AS t
WHERE t.rowIndex IN (FLOOR(@rowIndex / 2), CEIL(@rowIndex / 2));

谢谢。

编辑:

为了将来参考,这是我提出的最终查询:

# Write your MySQL query statement below
WITH s1 as (
    SELECT ROW_NUMBER() OVER (ORDER BY s.id) as rowIndex, s.*
    FROM Stadium as s
    WHERE s.people >= 100
    GROUP BY s.id, s.visit_date, s.people
), s2 as (
    SELECT COUNT(s.id) OVER (PARTITION BY s.id-s.rowIndex) as groupSize, s.*
    FROM s1 as s
)

SELECT s3.id, s3.visit_date, s3.people
FROM s2 as s3
GROUP BY s3.groupSize, s3.id, s3.visit_date, s3.people
HAVING s3.groupSize >= 3
ORDER BY s3.visit_date

标签: mysqlsqlcommon-table-expression

解决方案


您确认您使用的是 MySQL 8.0.21 服务器,所以我唯一的其他建议是您尝试在一次调用中运行两个 SQL 语句:

SET @rowIndex := 0;

WITH s1 as (
  SELECT...

大多数 MySQL 连接器默认不支持多查询。换句话说,您每次调用只能执行一个语句。一旦 MySQL在您的第一个语法之后看到任何;语法,它就会将其视为语法错误。

您没有理由需要使用多查询。只需分别运行这两个语句。只要您使用相同的会话,您的值@rowIndex将可用于后续语句。

MySQL 的前工程总监曾经告诉我,“没有理由应该存在多查询。”


推荐阅读