【问题标题】:How does mysql define DISTINCT() in reference documentationmysql如何在参考文档中定义DISTINCT()
【发布时间】:2011-01-29 09:32:54
【问题描述】:

编辑: 这个问题是关于在 SELECT 修改关键字和函数上找到对 MySQL 语法的明确参考。 /编辑

AFAIK SQL 定义了 DISTINCT 关键字的两种用途 - SELECT DISTINCT field... 和 SELECT COUNT(DISTINCT field) ... 但是,在我管理的一个 Web 应用程序中,我注意到像

这样的查询存在性能问题
SELECT DISTINCT(field1), field2, field3 ...

单列上的 DISTINCT() 没有意义,我几乎可以肯定它被解释为

SELECT DISTINCT field1, field2, field3 ...

但是我该如何证明呢?

我已经在 mysql 站点上搜索了有关此特定语法的参考,但找不到任何内容。有没有人有 mysql 中 DISTINCT() 定义的链接或知道其他权威来源?

最好的

编辑 在 mysql 论坛上问了同样的问题后,我了解到,在解析 SQL 时,mysql 并不关心函数和列名之间的空格(但我仍然缺少参考)。

看起来你可以在函数和括号之间有空格

SELECT LEFT (field1,1), field2...

让mysql理解为SELECT LEFT(field,1)

类似地 SELECT DISTINCT(field1), field2... 似乎被分解为 SELECT DISTINCT (field1), field2... 然后 DISTINCT 不被视为一些未定义(或未记录)的函数,而是作为 SELECT 修改关键字和 field1 周围的括号被评估为好像它们是字段表达式的一部分。

如果有人能提供指向说明函数和括号之间的空白不重要的文档的指针,或者提供指向适当的 MySQL 论坛、邮件列表的链接,我可以在其中提出问题并将其放入参考。

编辑 我找到了对服务器选项IGNORE SPACE 的引用。 它指出“IGNORE SPACE SQL 模式可用于修改解析器如何处理对空格敏感的函数名称”,后来它指出最近版本的 mysql 已将此数字从 200 减少到 30。

例如,剩下的 30 个中的一个是 COUNT。 同时启用 IGNORE SPACE

SELECT COUNT(*) FROM mytable;
SELECT COUNT (*) FROM mytable;

是合法的。

因此,如果这是一个例外,我只能得出结论,通常函数默认会忽略空格。

如果函数默认忽略空格,那么如果上下文不明确,例如对于 select 表达式的第一项上的第一个函数,那么它们与关键字无法区分,并且不能抛出错误,MySQL 必须接受它们作为关键字。

不过,我的结论感觉他们有很多假设,我仍然会很感激并接受任何指示,看看在哪里跟进。

【问题讨论】:

  • 你是说mysql的 SELECT DISTINCT(field1), field2, field3 ... 相当于postgres的 DISTINCT ON () 吗?另外,我真的很想找一些mysql的权威参考...
  • 只是运行一些测试来仔细检查,但我可以确认 mysql 的 SELECT DISTINCT() 在 postgres 中的行为不像 DISTINCT ON ()

标签: mysql


【解决方案1】:

为了完整起见,我正在回答我自己的问题并链接到我自己的另一个 question。 这种行为似乎是 SQL 标准允许函数和括号之间有空格的直接结果。

既然(通常)允许说 FUNCTION_NAME (x),那么当这个函数应用于 select 的第一项时

SELECT FUNCTION_NAME (x)

那么解析器将很难确定这是函数名的上下文还是 SELECT 修改关键字的上下文。

所以在上述情况下,FUNCTION_NAME 实际上是解析器的 FUNCTION_NAME_OR_KEYWORD。

但它更进一步:由于函数名和括号之间的空格是允许的,解析器实际上无法区分

SELECT FUNCTION_NAME_OR_KEYWORD (x)

SELECT FUNCTION_NAME_OR_KEYWORD(x)

(它必须测试关键字以查看它们是否是函数),并且由于 (x) 将被解析为 x,因此对于 FUNCTION_NAME_OR_KEYWORD -> DISTINCT(以及所有其他 SELECT 修改关键字)之间没有区别

SELECT DISTINCT x, y, z, ...

SELECT DISTINCT(x), y, z, ...

QED,但没有硬引用(假设 standard 不关心函数名和括号之间的空格,我相信这是合理的,但我无法遵循 BNF 语法,以至于我可以引用确切的规则)。

注意:mysql 有一定数量的函数,它关心函数和括号之间的空格,但我相信这些是例外(因此服务器选项忽略它)

【讨论】:

    【解决方案2】:

    有趣的场景。

    如你所见,

    SELECT DISTINCT(a), b, c
    

    相当于:

    SELECT DISTINCT (a), b, c
    

    相当于:

    SELECT DISTINCT a, b, c
    

    即括号被视为表达式分组括号。

    有趣的是,在 VB6/VBScript 中出现了一个非常相似的问题,其中 (for Function(byref x)) Function(x)、Function x 和 Call Function(x) 都略有不同,它们通过引用传递的值 (Function( x) 传递对 (x) 表达式结果的引用,而不是 x)。

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2015-02-23
      • 2012-07-30
      • 1970-01-01
      • 2022-10-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      相关资源
      最近更新 更多