【问题标题】:OrderBy clause is resulting different result sets when order column having same data当 order 列具有相同数据时,OrderBy 子句会产生不同的结果集
【发布时间】:2013-07-29 12:06:54
【问题描述】:

我们有一个存储过程来返回基于页码和页面大小的记录集。排序由“CreateDateTime”列完成。如果所有记录的CreatedDateTime 的值相同,则它以不同的顺序给出结果集。行为不一致。

部分代码:

SET @FirstRec  = ( @PageNo - 1 ) * @PageSize 
SET @LastRec   = ( @PageNo *@PageSize + 1 )   

SELECT * 
FROM 
( 
      select ROW_NUMBER() OVER (ORDER BY CreatedDateTime)     
       AS rowNumber,EMPID 
      From Employee
) as KeyList 
WHERE rowNumber > @FirstRec AND rowNumber <  @LastRec

请就此提供一些意见。

【问题讨论】:

  • 您能否提供一些示例数据来了解什么是不一致?

标签: sql sql-server-2008 stored-procedures sql-order-by


【解决方案1】:

这是“设计使然”

如果未指定 ORDER BY 子句,SQL Server(或任何 RDBMS)不保证以特定顺序返回结果。有些人认为如果没有指定 order by 子句,则总是以聚集索引顺序或物理磁盘顺序返回行。但是,这是不正确的,因为在查询处理期间有许多因素可以改变行顺序。并行 HASH 连接是更改行顺序的运算符的一个很好的例子。

如果您指定ORDER BY 子句,SQL Server 将对行进行排序并按请求的顺序返回它们。但是,如果该顺序不是确定性的,因为您有重复的值,那么在每个“值组”中,由于上述相同的原因,顺序是“随机的”。

保证确定性顺序的唯一方法是在ORDER BY 子句中包含保证唯一的列或列组(例如主键)。

【讨论】:

    【解决方案2】:

    如果您需要可重复的订单,则需要确保在 ORDER BY 中指定足够的列,以便(ORDER BY 中列出的所有列的组合)对于每一行都是唯一的。例如。添加EmpID(如果这是主键)充当具有相等CreatedDateTime 值的行之间的“决胜局”。

    【讨论】:

      【解决方案3】:

      如果您订购的列中的值都相同,则不能保证它们会以相同的顺序检索。您可以 ORDER BY 第二列 - 如果有的话,也许是唯一的 id? (我在下面的代码中将其称为 UniqueId)。这将确保顺序始终相同。

      SELECT * 
      FROM 
      ( 
            select ROW_NUMBER() OVER (ORDER BY CreatedDateTime, UniqueId)     
             AS rowNumber,EMPID 
            From Employee
      ) as KeyList 
      WHERE rowNumber > @FirstRec AND rowNumber <  @LastRec
      

      【讨论】:

      • 这将首先按 CreatedDateTime 排序,然后按唯一 ID 排序。因此,不同时间的条目肯定会按正确的顺序排列。
      • 您甚至不必求助于 RowNumber() 函数。上面的一个更简单的版本是像往常一样实现你的排序,并添加一个唯一的 ID 作为最后一个排序。例如,我有类似 SELECT * FROM #tmp ORDER BY CreatedDateTime, UniqueId OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-16
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2010-09-11
      相关资源
      最近更新 更多