SQL Server UNION - 默认的ORDER BY行为是什么

时间:2009-01-07 16:43:19

标签: sql sql-server union sql-order-by

如果我有一些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个不同的表连接在一起以返回我想要的结果。

7 个答案:

答案 0 :(得分:42)

没有默认订单。

如果没有 Order By 子句,则返回的顺序是未定义的。这意味着SQL Server可以按照自己喜欢的顺序将它们带回来。

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

答案 1 :(得分:15)

关于添加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

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

答案 2 :(得分:10)

刚刚找到了实际答案。

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

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

答案 3 :(得分:7)

如果您关心返回记录的顺序,您必须使用订单。

如果你将其删除,它可能显示有组织(基于查询计划选择的索引),但你今天看到的结果可能不是你期望的结果,它甚至可能明天运行相同查询时更改。

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

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

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

  • Hugo Kornelis证明明显的顺序始终基于主键。 Here is his follow-up post有解释。

答案 4 :(得分:2)

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

然而,有一些隐式不同的算法,例如10g +中的Oracle哈希方法,不会对其进行排序。

正如DJ所说,总是使用ORDER BY

答案 5 :(得分:1)

通常会遇到编写不好的代码,假设表格数据是按插入顺序返回的,并且95%的时间编码器都会使用它,并且永远不会意识到这是一个问题,就像许多常见数据库一样(MSSQL ,Oracle,MySQL)。这当然是一个完整的谬误,并且总是在遇到时会被纠正,并且无一例外地自己使用Order By子句。

答案 6 :(得分:-2)

根据我的实践经验,您可以使用" UNION"来改变订单。反对" UNION ALL" ... 即 如果你的查询是

Select Count(*) from Table A
UNION 
Select Count(*) from Table B

result is
10
26

你可以通过替换" UNION"来翻转订单。与" UNION ALL" ... 那么结果将是

26
10