为什么SQL Server 2008在使用GROUP BY时订购并且没有指定订单?

时间:2010-10-14 22:56:05

标签: sql sql-server-2008 group-by sql-order-by

我遇到了一个非常奇怪的问题,我还没有找到任何解释。使用SQL Server 2008并使用GROUP BY,它会在没有指定任何ORDER BY的情况下对我的列进行排序。这是一个演示这种情况的脚本。

CREATE TABLE #Values ( FieldValue varchar(50) )

;WITH FieldValues AS
(
    SELECT '4' FieldValue UNION ALL
    SELECT '3' FieldValue UNION ALL
    SELECT '2' FieldValue UNION ALL
    SELECT '1' FieldValue
)
INSERT INTO #Values ( FieldValue )
SELECT
    FieldValue 
FROM FieldValues

-- First SELECT demonstrating they are ordered DESCENDING
SELECT
    FieldValue
FROM #Values

-- Second SELECT demonstrating they are ordered ASCENDING
SELECT
    FieldValue
FROM #Values
GROUP BY
    FieldValue

DROP TABLE #Values

第一个SELECT将返回

4
3
2
1

第二个SELECT将返回

1
2
3
4

根据它所说的MSDN Documentation:“ GROUP BY子句不对结果集进行排序

4 个答案:

答案 0 :(得分:13)

要回答这个问题,请查看两者产生的查询计划。

第一个SELECT是简单的表扫描,这意味着它按分配顺序生成行。由于这是一个新表,它与您插入记录的顺序相匹配。

第二个SELECT添加了GROUP BY,SQL Server通过一个不同的排序实现,因为估计的行数太低了。如果您有更多行或向SELECT添加聚合,此运算符可能会更改。

例如,尝试:

CREATE TABLE #Values ( FieldValue varchar(50) )

;WITH FieldValues AS
(
    SELECT '4' FieldValue UNION ALL
    SELECT '3' FieldValue UNION ALL
    SELECT '2' FieldValue UNION ALL
    SELECT '1' FieldValue
)
INSERT INTO #Values ( FieldValue )
SELECT
    A.FieldValue
FROM FieldValues A
CROSS JOIN FieldValues B
CROSS JOIN FieldValues C
CROSS JOIN FieldValues D
CROSS JOIN FieldValues E
CROSS JOIN FieldValues F

SELECT
    FieldValue
FROM #Values
GROUP BY
    FieldValue

DROP TABLE #Values

由于行数,这会变为哈希聚合,现在查询计划中没有排序。

如果没有ORDER BY,SQL Server可以按任何顺序返回结果,它返回的顺序是它认为最快速返回数据的副作用。

答案 1 :(得分:6)

如果未指定order by子句,SQLServer可以按任何顺序自由返回结果。

也许在您的特定查询中,它将返回已排序的结果,但这并不意味着在使用group by子句时始终对resltsets进行排序。

也许(只是可能)它正在做一些散列聚合来计算分组,哈希表恰好按1,2,3,4排序。然后以哈希顺序返回行...

答案 2 :(得分:1)

这是一个数据库优化方面。 SQL引擎通常必须按分组列的顺序解析数据。它不是浪费时间,而是以解析的任何顺序离开数据集。

在某些情况下情况并非如此(特别是如果使用聚合函数)。使用ORDER BY命令显然会覆盖此功能(因此意味着一点额外的负载,但在最极端的情况下除此之外不足以担心)。

答案 3 :(得分:1)

您也可以在这里清理插入语句。 SQL Server 2008为插入添加了一项新功能。例如:

进入tbl(clmn) 值(1),         (2),         (3) 每条记录都不需要它自己的insert语句,每条记录都以逗号分隔。