【问题标题】:Where is the syntax error in this WITH clause?这个 WITH 子句的语法错误在哪里?
【发布时间】:2020-10-29 19:26:57
【问题描述】:

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

桌子:体育场

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

visit_date 是该表的主键。此表的每一行 包含访问日期和访问 id 到体育场的次数 访问期间的人。没有两行会有相同的访问日期, 随着 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人参加。请注意,第 8 行甚至包括在内 虽然 visit_date 不是第 7 行之后的第二天。 id 2 和 3 不包括在内,因为我们至少需要三个 连续的 id。

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

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

# 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 服务器版本,以便使用正确的语法 'WITH s1 (rowIndex, id, visit_date, people) as ( 在第 4 行选择 @rowIndex := @rowInde'

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

我使用下面的查询作为参考。 (Original.)

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

【问题讨论】:

  • 请提供样本数据和期望的结果。有更好的方法来编写这个逻辑。
  • 我在尝试您的代码时收到的语法错误是“ERROR 1146 (42S02): Table 'test.stadium' doesn't exist”,这意味着您没有提供问题的完整详细信息... .
  • 我建议您运行查询SELECT @@version; 以确认服务器 是8.0。您可能正在使用 MySQL 8.0 客户端,但这并不意味着将支持 WITH 语法。
  • 为什么不直接使用row_number() 而不是@rowindex hack?
  • @user8629729 MySQL 8.0 在ROW_NUMBER 旁边引入了公共表表达式,这应该可以简化查询

标签: mysql sql common-table-expression


【解决方案1】:

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

SET @rowIndex := 0;

WITH s1 as (
  SELECT...

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

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

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

【讨论】:

  • 感谢添加答案。在 SET 分配导致相同的语法错误之后,删除 ; 似乎。 ' 我不熟悉多查询,但我会坚持下去!
  • 你误会了。问题不在于分号。它是分号后面的所有内容。每次通话只能做一个声明。
  • 我明白了......所以如果我想坚持使用用户变量策略,我可以运行 SET 命令,清除编辑器,然后运行第二个查询。这就是你的意思,对吗? (我试过这个来测试,它成功了!没有语法错误。)
【解决方案2】:
  • 不确定你可能会遇到什么问题,但这会传递给 LeetCode:

  • 不确定这是否是正确的做法:

SELECT DISTINCT S1.id,
                S1.visit_date,
                S1.people
FROM stadium AS S1,
     stadium AS S2,
     stadium AS S3
WHERE S1.people > 99
  AND S2.people > 99
  AND S3.people > 99
  AND ( (S2.id = S1.id + 1
         AND S3.id = S1.id + 2)
       OR (S2.id = S1.id - 1
           AND S3.id = S1.id + 1)
       OR (S2.id = S1.id - 1
           AND S3.id = S1.id - 2) )
ORDER BY id ASC;

【讨论】:

    猜你喜欢
    • 2016-09-29
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 2012-11-08
    • 2014-03-20
    • 1970-01-01
    相关资源
    最近更新 更多