为什么 ROW_NUMBER OVER(ORDER BY 列)返回的结果顺序与 ORDER BY 列不同?

发布于 2024-09-03 23:44:18 字数 1121 浏览 6 评论 0原文

我使用的是 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

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

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

I'm on SQL Server 2008, using NHibernate as persistence layer (although this problem is purely SQL, I believe).

I've boiled down my problem to the following SQL statement:

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 */

This is part of the query that NH generates for retrieving a paged result set. The above statement gives me the following result:

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

However, if I omit the ROW_NUMBER() OVER (ORDER BY this_.IsActive) - which is what NH generates for retrieving results on the first page - I get two completely different table entries in my result:

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 */

returns

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

This completely confuses me and leads to a bug in our app where I get the same Campsite entry as the first element on the first AND the second page of our search.

Why does the same ORDER BY clause work differently inside the ROW_NUMBER OVER() expression?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

内心激荡 2024-09-10 23:44:18

ORDER BY this_.IsActive /* 一个位字段 */

因为这是一个位字段,所以它只能是 0 或 1...我假设你有很多行,这个位字段是 0 或 1,按这样排序并不会使从某种意义上说,如果 90% 处于活动状态怎么办...在这种情况下,您实际上并没有正确订购,因为您没有第二次订购。

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

或者这个怎​​么样?

ROW_NUMBER() OVER (ORDER BY this_.IsActive, this_.Name) 

ORDER BY this_.IsActive /* a bit field */

since that is a bit field it can only be 0 or 1...I assume you have many rows with this bit field being 0 or 1 ordering it by that doesn't make sense, what if 90% is active...you are not really ordering correctly in that case because you don't have a second ordering.

why don't you pick something that is unique...maybe his_.Name for example

or what about this?

ROW_NUMBER() OVER (ORDER BY this_.IsActive, this_.Name) 
总攻大人 2024-09-10 23:44:18

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

注意:

  • 内部 ORDER BY 适用于 ROW_NUMBER() 值排序。
  • 您的输出 ORDER BY 是 only this_.IsActive

It's basically random in both instances because a bit field is bad for any ordering (as SQL Menace noted). They are separately evaluated by the DB Engine because they have nothing to do with each other.

Note:

  • The internal ORDER BY only applies to the ROW_NUMBER() value ordering.
  • Your output ORDER BY is only this_.IsActive
初与友歌 2024-09-10 23:44:18

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

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

You expect the result to be ordered by Name too, but only have IsActive in the ORDER BY clause.

The nature of SELECT is set-based, so you should not rely on arbitrary (but seemingly correct) ordered results of your query if you do not explicitly define the order.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文