mysql - 哪些 DBMS 允许对 select 子句中不存在的属性进行排序?

标签 mysql sql-server oracle db2 sql-order-by

假设我有一个名为 Cars 的表,其中包含 2 列:CarNameBrandName

现在我要执行这个查询:

select CarName
from Cars
order by BrandName

如您所见,我想返回一个按列排序的列表,该列不存在于查询的选择部分。

sql命令的基本(未优化)执行顺序是:from, where, group by, having, select, order by.

出现的问题是,BrandName 不是执行选择命令后剩下的部分。

我在书籍、谷歌和 Stackoverflow 上搜索过这个,但到目前为止我只找到了几个 SO 评论,比如“我知道数据库系统不允许它,但我不记得是哪个一”。

所以我的问题是:
1) 标准是什么SQL-92或者 SQL99 说说这个。
2)哪些数据库允许这个查询,哪些不允许?

(背景:几个学生问这个,我想给他们最好的答案)

编辑:
- 成功测试 Microsoft SQL Server 2012

最佳答案

您的查询是完全合法的语法,您可以按选择中不存在的列进行排序。

如果您需要有关合法排序的完整规范,在 SQL Standard 2003 中有一长串关于排序依据应该包含和不应该包含的内容的语句,(02-Foundation,第 415 页,第 7.13 节 ,子部分 28)。这确认您的查询是合法语法。

我认为您的困惑可能是由于按组中不存在的列进行选择和/或排序,或者在使用不同时按不在选择中的列进行排序。

两者都有相同的基本问题,据我所知,MySQL 是唯一允许其中任何一个的问题。

问题是这样的,当使用 group by 或 distinct 时,任何不包含在其中的列都不需要,所以如果它们在行中有多个不同的值并不重要,因为它们永远不需要。想象一下这个简单的数据集:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |
2   |    A    |    Z     |
3   |    B    |    Y     |

如果你写:

SELECT  DISTINCT Column1
FROM    T;

你会得到

 Column1 
---------
     A   
     B   

如果您随后添加 ORDER BY Column2,您将使用两个 column2 中的哪一个来按 X 或 Z 对 A 进行排序?如何为 column2 选择一个值是不确定的。

这同样适用于选择不在分组依据中的列。为简化起见,想象一下上表的前两行:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |
2   |    A    |    Z     |

在MySQL中你可以写

SELECT  ID, Column1, Column2
FROM    T
GROUP BY Column1;

这实际上违反了 SQL 标准,但它在 MySQL 中有效,但问题是它是不确定的,结果:

ID  | Column1 | Column2  |
----|---------+----------|
1   |    A    |    X     |

不比

更正确或更不正确
ID  | Column1 | Column2  |  
----|---------+----------|
2   |    A    |    Y     |

所以你的意思是为 Column1 的每个不同值提供一行,两个结果集都满足,那么你怎么知道你会得到哪一个?嗯,你没有,这似乎是一个相当普遍的误解,你可以添加和 ORDER BY 子句来影响结果,例如下面的查询:

SELECT  ID, Column1, Column2
FROM    T
GROUP BY Column1
ORDER BY ID DESC;

将确保您获得以下结果:

ID  | Column1 | Column2  |  
----|---------+----------|
2   |    A    |    Y     |

因为 ORDER BY ID DESC,但这不是真的 (as demonstrated here)。

MySQL documents状态:

The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.

因此,即使您有订单,但在每组选择一行之后才会应用,并且这一行是不确定的。

SQL 标准确实允许选择列表中的列不包含在 GROUP BY 或聚合函数中,但是这些列必须在功能上依赖于 GROUP BY 中的列。来自 SQL-2003-Standard(5WD-02-Foundation-2003-09 - 第 346 页)- http://www.wiscorp.com/sql_2003_standard.zip

15) If T is a grouped table, then let G be the set of grouping columns of T. In each <value expression> contained in <select list> , each column reference that references a column of T shall reference some column C that is functionally dependent on G or shall be contained in an aggregated argument of a <set function specification> whose aggregation query is QS.

例如,示例表中的ID是PRIMARY KEY,所以我们知道它在表中是唯一的,所以下面的查询符合SQL标准,在MySQL中运行,目前在很多DBMS中都失败(当时编写 Postgresql 是我所知道的最接近正确实现标准的 DBMS - Example here):

SELECT  ID, Column1, Column2
FROM    T
GROUP BY ID;

由于每一行的 ID 都是唯一的,因此每个 ID 只能有一个 Column1 值,一个 Column2 值,对于返回什么没有歧义每行。

关于mysql - 哪些 DBMS 允许对 select 子句中不存在的属性进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20356656/

相关文章:

php - 在php中获取url id并检查它是否存在于数据库中

sql - 根据最大值连接表

oracle - JDBC 连接失败并出现 ORA-12516

java - 有没有办法检查特定的 jdk(Oracle 或 OpenJDK)是否支持 Java Flight Recorder?

php - 迭代表中的列表值

mysql - 从 MySQL 中的列中删除 NOT NULL 限制

javascript - 在 Nodewebkit 中使用 MySQL(嵌入式)

c# - 存储过程的返回值仅在 ASP.NET 中获取第一个字符

c - 无法将 C 程序变量绑定(bind)到 SQL Server 中的日期时间类型列

java - 一张表的并发更新和删除