使用带关系的 ROW_NUMBER() OVER 十进制列时未确定的排序顺序

Posted

技术标签:

【中文标题】使用带关系的 ROW_NUMBER() OVER 十进制列时未确定的排序顺序【英文标题】:Undetermined sort order when using ROW_NUMBER() OVER decimal column with ties 【发布时间】:2011-10-27 16:39:54 【问题描述】:

我的 sql server 2008 有一个非常奇怪的错误:

要在 CRUD 应用程序详细信息视图中显示寻呼机,我发出 sql 请求以获取相对于当前记录的上一条和下一条记录,它运行良好,除非在 DECIMAL 列上排序时,我可以将问题减少到该查询( FTE 是十进制 (18,2)):

WITH [IndexedRows] AS (
    SELECT 
        [ContactId], 
        [ContactCode],
        [FTE],
        [EmployeeName], 
        ROW_NUMBER() OVER ( ORDER BY [FTE] ASC ) AS [RowIndex]
    FROM   
        [Vw_HrEmployee]
)

/* 1. I can see ContactId 1109 is rowindex 7 */
/*SELECT * FROM [IndexedRows];*/

/* 2. Get the RowIndex, it returns 7 */
/*SELECT [RowIndex] 
FROM   [IndexedRows] 
WHERE  [ContactId] = 1109;*/

/* 3. Why it doesn't returns ContactId 1109 ??? */
SELECT [ContactId], 
       [EmployeeName] 
FROM   [IndexedRows] 
WHERE [RowIndex] = 7;

我得到了另一个具有相同 FTE 值的人的 contactId,但我不明白为什么 WHERE 行索引没有返回正确的行(如果我显示 IndexedRows,它看起来不错!)。

我认为这并不重要,但 Vw_HrEmployee 是一个视图。

欢迎任何帮助/想法/解决方法来解决这个问题,

提前致谢

【问题讨论】:

您说“我得到了另一个具有相同 FTE 值的人的 contactId”如果您与 FTE 值有关联,那么它们在关联组中的编号方式将是不确定的,所以这是预期的行为。 你的补丁级别是多少?我记得在 CU5(?)之前遇到了 SQL 2008 CTE 的问题。虽然我认为自 SP2 以来我们没有遇到任何问题。 您是否 100% 肯定所有 FTE 值都是唯一的,从而创建确定性排序顺序?任何重复值和您的 ROW_NUMBER() 输出都未确定。 select isn't broken: codinghorror.com/blog/2004/10/a-pragmatic-quick-reference.html 你说得对,排序不是确定性的,我不应该依赖 sql server 显示特定顺序的事实。 【参考方案1】:

这是一个猜测,但如果您的 FTE 值有重复值,则无法保证每次运行代码时它们会以什么顺序出现。当您使用 WHERE 条件执行简单的 SELECTSELECT 时,SQL Server 可能会更改查询计划,从而导致出现的顺序和您所看到的不同。

我会将 PK 添加到您的 ORDER BY 的末尾,以确保顺序始终一致。

【讨论】:

就是这样!我接受你的回答,因为在我的情况下,主键想法的排序也非常方便,谢谢!【参考方案2】:

也许添加另一个排序标准以帮助确保正确/所需的顺序?

ROW_NUMBER() OVER ( ORDER BY [FTE] ASC, 
                             BirthDate ASC, 
                             AstrologySign DESC ) AS [RowIndex] 

【讨论】:

感谢您的回答,实际上排序取决于用户如何对上一页中的网格进行排序,我认为更改它会出现问题,但我会尝试,因为它应该使所有行排序显式)

以上是关于使用带关系的 ROW_NUMBER() OVER 十进制列时未确定的排序顺序的主要内容,如果未能解决你的问题,请参考以下文章

ROW_NUMBER() OVER()函数用法详解

浅谈ROW_NUMBER() OVER()函数的使用

ROW_NUMBER() OVER()

row_number()over()使用

使用 Row_number() OVER(partition BY..) 以及声明局部变量

关于Oracle row_number() over()的简单使用