3

我在 SQL Server 2008 上,使用 NHibernate 作为持久层(尽管我相信这个问题纯粹是 SQL)。

我将问题归结为以下 SQL 语句:

SELECT TOP 2
    this_.Id   as Id36_0_,
    this_.Name as Name36_0_,
    ROW_NUMBER() OVER (ORDER BY this_.IsActive) as MyOrder
FROM    Campsites this_
ORDER BY this_.IsActive  /* a bit field */

这是 NH 为检索分页结果集而生成的查询的一部分。上面的语句给了我以下结果:

Id36_0_ Name36_0_                       MyOrder
9806    Camping A Cassagnau                 1
8869    Camping a la ferme La Bergamotte    2

但是,如果我省略 ROW_NUMBER() OVER (ORDER BY this_.IsActive) - 这是 NH 为在第一页上检索结果而生成的 - 我会在结果中得到两个完全不同的表条目:

SELECT   TOP 2
    this_.Id   as Id36_0_,
    this_.Name as Name36_0_
    /* ROW_NUMBER() OVER(ORDER BY this_.IsActive) as MyOrder */
FROM     Campsites this_
ORDER BY this_.IsActive  /* a bit field */

返回

Id36_0_ Name36_0_
22876   Centro Vacanze Pra delle Torri
22135   Molecaten Park Napoleon Hoeve

这完全让我感到困惑,并导致我们的应用程序出现错误,在该错误中,我得到与搜索的第一页和第二页上的第一个元素相同的 Campsite 条目。

为什么相同的 ORDER BY 子句在 ROW_NUMBER OVER() 表达式中的工作方式不同?

4

3 回答 3

5

ORDER BY this_.IsActive /* 一个位域 */

因为那是一个位字段,它只能是 0 或 1...我假设您有很多行,此位字段为 0 或 1 排序它没有意义,如果 90% 处于活动状态...你在这种情况下并没有真正正确订购,因为您没有第二次订购。

你为什么不选择一些独特的东西......也许是他的_。例如名字

或者这个呢?

ROW_NUMBER() OVER (ORDER BY this_.IsActive, this_.Name) 
于 2010-06-01T19:21:56.747 回答
3

在这两种情况下它基本上都是随机的,因为位字段对于任何排序都是不利的(如 SQL Menace 所述)。它们由数据库引擎单独评估,因为它们彼此无关。

笔记:

  • 内部 ORDER BY适用于 ROW_NUMBER() 值排序。
  • 您的输出 ORDER BY只是this_.IsActive
于 2010-06-01T19:22:15.553 回答
3

您希望结果也按名称排序,但在 ORDER BY 子句中只有 IsActive。

SELECT 的本质是基于集合的,因此如果您没有明确定义顺序,则不应依赖查询的任意(但看似正确)有序结果。

于 2010-06-01T19:26:36.157 回答