代码之家  ›  专栏  ›  技术社区  ›  Unreason

MySQL如何在参考文档中定义distinct()。

  •  2
  • Unreason  · 技术社区  · 15 年前

    编辑: 这个问题是关于在选择修改关键字和函数时找到对MySQL语法的明确引用。 编辑

    afaik sql定义了两种不同关键字的用法-select distinct field…并选择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)

    同样,选择distinct(field1),field2…好像被分解成 选择distinct(field1),field2…然后,distinct不是作为未定义(或未记录)的函数,而是作为select modifying关键字,field1周围的括号被计算为字段表达式的一部分。

    如果有人有一个指向文档的指针,说明函数和括号之间的空白空间不重要,或者提供指向MySQL论坛的链接,邮件列表,在这里我可以提出一个问题以供参考。

    编辑 我找到了对服务器选项的引用 IGNORE SPACE . 它指出“可以使用忽略空间SQL模式来修改解析器如何处理对空格敏感的函数名”,随后它指出,MySQL的最新版本已经将这个数字从200减少到30。

    例如,剩余30个中的一个是count。 同时启用忽略空间

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

    是合法的。

    所以如果这是一个例外,我就可以得出这样的结论:通常函数默认忽略空格。

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

    尽管如此,我的结论似乎有很多假设,我还是会感激并接受任何建议,看看该从何处跟进。

    2 回复  |  直到 15 年前
        1
  •  4
  •   Community CDub    8 年前

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

    因为它(通常)允许说函数名(x),所以当这个函数应用于第一个选择项时

    SELECT FUNCTION_NAME (x)
    

    如果这是一个函数名的上下文或者选择修改关键字,那么解析器将很难确定。

    所以在上面的例子中,函数名实际上是解析器的函数名或关键字。

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

    SELECT FUNCTION_NAME_OR_KEYWORD (x)
    

    SELECT FUNCTION_NAME_OR_KEYWORD(x)
    

    (它必须测试关键字以查看它们是否是函数),由于(x)将被解析为x,因此对于函数“name”或“u keyword”->“distinct”(以及所有其他选择修改关键字),两者之间没有区别

    SELECT DISTINCT x, y, z, ...
    

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

    QED,但没有硬引用(假设 standard 不关心函数名和圆括号之间的空白,我相信是合理的,但是我不能按照BNF语法来引用确切的规则)。

    注意:MySQL有一定数量的函数,它关心函数和括号之间的空白,但我相信这些是异常的(因此服务器选项可以忽略它)。

        2
  •  1
  •   Cade Roux    15 年前

    有趣的场景。

    正如你发现的,

    SELECT DISTINCT(a), b, c
    

    相当于:

    SELECT DISTINCT (a), b, c
    

    相当于:

    SELECT DISTINCT a, b, c
    

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

    有趣的是,vb6/vbscript中出现了一个非常相似的问题,其中(对于函数(byref x))函数(x)、函数x和调用函数(x)都略有不同,它们通过引用传递的值(函数(x)传递对(x)表达式结果的引用,而不是x)传递的引用。