SQL:对具有空值的列进行排序时,行号不同

SQL: Row number is different when sorting on columns with null values

在我的 C# 应用程序中,我使用以下查询来搜索特定字符串:

;WITH selectRows AS (SELECT *, row = ROW_NUMBER() OVER (ORDER BY <column_name>) FROM <table_name>)
SELECT row FROM selectRows WHERE <column_name> LIKE '%<search_string>%' COLLATE <collate> ORDER BY row;

这个特定的查询对我来说总是很好,即使 OVER ORDER BY 子句的 colum_name 是一个包含空值的列。昨天我尝试搜索更大的 SQL table(+- 100 万条记录),令我惊讶的是我在执行之间没有更改查询的情况下返回了不同的 row_numbers。这似乎只发生在更大的 table 上,并且当 OVER ORDER BY 子句的 column_name 包含任何空值时。当 column_name 指向没有空值的列时,查询 returns 一遍又一遍地得到相同的结果。

我也尝试了以下查询,但效果不佳:

;WITH selectRows AS (SELECT *, row = ROW_NUMBER() OVER (ORDER BY ISNULL(<column_name>, '')) FROM <table_name>)
SELECT row FROM selectRows WHERE <column_name> LIKE '%<search_string>%' COLLATE <collate> ORDER BY row;

注意:两个查询都在 SQL Server 2012 和 SQL Server 2008 上进行了测试。搜索到的 table 在身份列上也有一个主键(聚集)索引和一个column_name 上用于 OVER ORDER BY 子句的非聚集索引。

提前致谢!

您指定的订购标准不是总订单。示例:您对始终为零的列进行排序。这样 CTE 每次都可以输出不同的行顺序。

您在订购 之后过滤。这意味着您的过滤器每次都在不同的行上运行。它可能恰好有很多匹配行或没有。

通常 SQL 由于某些构造,查询不是 100% 确定性的。不止这个

修复:指定总订单。使用 anything 打破平局,例如 ORDER BY X, ID。作为一个习惯,我总是指定总订单。