代码之家  ›  专栏  ›  技术社区  ›  Nathan Palmer

为什么在使用GROUP BY而未指定顺序时,SQL Server 2008会排序?

  •  4
  • Nathan Palmer  · 技术社区  · 14 年前

    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
    

    4
    3
    2
    1
    

    第二个选择将返回

    1
    2
    3
    4
    

    根据 MSDN Documentation GROUPBY子句不对结果集排序

    4 回复  |  直到 14 年前
        1
  •  13
  •   Tadmas    14 年前

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

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

    第二个SELECT添加一个GROUP BY,由于估计的行数很低,所以SQL Server通过一个不同的排序来实现它。如果要有更多行或向选定内容添加聚合,则此运算符可能会更改。

    例如,尝试:

    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
    

    由于行数的原因,这将更改为哈希聚合,现在查询计划中没有排序。

        2
  •  6
  •   Pablo Santa Cruz    14 年前

    如果不指定ORDERBY子句,SQLServer可以按任意顺序返回结果。

    可能在您的特定查询中,它将返回按顺序排列的结果,但这并不意味着它将 总是

        3
  •  1
  •   Maltronic    14 年前

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

    有时情况并非如此(尤其是使用聚合函数时)。使用ORDER BY命令显然会覆盖这个功能(因此意味着有一点额外的负载,除了最极端的情况之外,根本不需要担心)。

        4
  •  1
  •   Salizar Marxx    14 年前

    您也可以在这里清理insert语句。

    数值(1), (二), (三) 每个记录不需要自己的insert语句,每个记录都由coma分隔。