39

如果我有几个 UNION 语句作为人为的例子:

SELECT * FROM xxx WHERE z = 1
UNION 
SELECT * FROM xxx WHERE z = 2
UNION
SELECT * FROM xxx WHERE z = 3

默认order by行为是什么?

我看到的测试数据基本上不会按照上面指定的顺序返回数据。即数据是有序的,但我想知道这方面的优先规则是什么。

另一件事是,在这种情况下,xxx 是一个视图。该视图将 3 个不同的表连接在一起以返回我想要的结果。

4

6 回答 6

46

没有默认顺序。

如果没有Order By子句,则返回的订单是未定义的。这意味着 SQL Server 可以按照它喜欢的任何顺序恢复它们。

编辑:根据我所看到的,没有 Order By,结果返回的顺序取决于查询计划。因此,如果它正在使用一个索引,则结果可能会按该顺序返回,但同样不能保证。

于 2009-01-07T16:48:34.647 回答
17

关于添加 ORDER BY 子句:

这对大多数人来说可能是基本的,但我想我添加了这个。有时您不希望结果混合在一起,因此您需要第一个查询的结果,然后是第二个,依此类推。为此,我只需添加一个虚拟的第一列并按此排序。由于忘记为联合中的列命名可能存在问题,我通常在 order by 子句中使用序数,而不是列名。

例如:

SELECT 1, * FROM xxx WHERE z = 'abc'
UNION ALL
SELECT 2, * FROM xxx WHERE z = 'def'
UNION ALL
SELECT 3, * FROM xxx WHERE z = 'ghi'
ORDER BY 1

当我要运行两个查询并且我知道只有一个会返回任何结果时,虚拟序数列也很有用。然后我可以检查返回结果的序数。这使我不必进行多次数据库调用和大多数空结果集检查。

于 2009-01-08T17:08:40.830 回答
12

刚刚找到实际答案。

因为 UNION 会删除重复项,所以它会执行 DISTINCT SORT。这是在连接所有 UNION 语句之前完成的(查看执行计划)。

要停止排序,请执行 UNION ALL,这也不会删除重复项。

于 2009-03-11T11:48:59.583 回答
8

如果您关心返回记录的顺序,则必须使用 order by。

如果您忽略它,它可能会显得井井有条(基于查询计划选择的索引),但是您今天看到的结果可能不是您期望的结果,甚至在明天运行相同的查询时它甚至可能会发生变化。

编辑:一些好的,具体的例子:(所有例子都是 MS SQL 服务器)

  • Dave Pinal 的博客描述了两个非常相似的查询如何显示不同的明显顺序,因为使用了不同的索引:

    SELECT ContactID FROM Person.Contact
    SELECT *         FROM Person.Contact
    
  • Conor Cunningham展示了当表变大时(如果查询优化器决定使用并行执行计划),表观顺序会如何变化。

  • Hugo Kornelis证明了明显的顺序并不总是基于主键。这是他的后续帖子,并附有解释。

于 2009-01-07T18:27:22.513 回答
2

UNION 在结果集排序方面可能具有欺骗性,因为数据库有时会使用排序方法来提供 UNION 中隐含的 DISTINCT,这使得行看起来像是故意排序的——这不适用于 UNION ALL当然,其中没有隐含的不同。

但是有一些隐式 distinct 算法,例如 Oracle 在 10g+ 中的散列方法,不会应用排序。

正如 DJ 所说,始终使用 ORDER BY

于 2009-01-07T18:15:49.480 回答
1

遇到写得不好的代码假设表数据以插入顺序返回是很常见的,95% 的时间编码人员都没有意识到这是一个问题,就像在许多常见数据库(MSSQL、Oracle、 MySQL)。这当然是一个完全的谬误,当遇到它时应始终予以纠正,并且始终无一例外地自己使用 Order By 子句。

于 2009-01-07T18:31:55.547 回答