mysql如何在参考文档中定义DISTINCT()

时间:2010-03-19 09:59:40

标签: mysql

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

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

之类的查询的性能问题
SELECT DISTINCT(field1), field2, field3 ...

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

SELECT DISTINCT field1, field2, field3 ...

但我怎么能证明这一点?

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

最佳

EDIT 在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论坛,邮件列表的链接,我可以提出一个问题将其放入参考

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

其余30个中的一个是例如COUNT。 启用IGNORE SPACE后

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

是合法的。

因此,如果这是一个例外,我可以得出结论,通常函数默认忽略空间。

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

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

2 个答案:

答案 0 :(得分:4)

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

由于(通常)允许说FUNCTION_NAME(x),然后将此功能应用于第一个选择

SELECT FUNCTION_NAME (x)

然后解析器将很难确定这是否是函数名称或SELECT修改关键字的上下文。

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

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

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有一定数量的函数,它关心函数和括号之间的空格,但我相信这些是异常(因此忽略它的服务器选项)

答案 1 :(得分:1)

有趣的场景。

如你所见,

SELECT DISTINCT(a), b, c

相当于:

SELECT DISTINCT (a), b, c

相当于:

SELECT DISTINCT a, b, c

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

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