2010-06-01 23 views
3

我在SQL Server 2008上,使用NHibernate作为持久层(尽管这个问题纯粹是SQL,我相信)。为什么ROW_NUMBER OVER(ORDER BY列)返回的结果顺序与ORDER BY列不同?

我归结我的问题下面的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 

但是,如果我忽略OVER(ORDER BY this_.IsActive)的ROW_NUMBER() - 这正是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()表达式中以不同的方式工作?

+0

很奇怪,因为对于2005方言,row_number列总是被命名为'__hibernate_sort_row',并且顺序总是使用该列。 – dotjoe 2010-06-01 20:50:16

回答

3

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

注:

  • 内部ORDER BY 适用于ROW_NUMBER()值排序。
  • 你的输出ORDER BY是只有 this_.IsActive
+0

感谢您的洞察力。这是有道理的。所以我的问题应该是:NHibernate为什么这样做?我应该为此提出一个新问题吗? – Oliver 2010-06-01 19:57:02

+0

我会开一个新的问题。这是一个NHibernate的问题,而不是SQL。这很奇怪,如果这是NHibernate所做的,除非它使用新列对客户端进行排序。但是,尽管在大多数数据库引擎中这是基本的SQL东西。 – gbn 2010-06-01 20:09:51

5

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

,因为这是一个位字段只能是0或1 ...我假设你有此位字段为0或1个多行通过这种排序是没有意义的,如果90%是活跃的,那么该怎么办?在这种情况下,您并没有正确排序,因为您没有第二个排序。

你为什么不挑东西是独一无二的......也许his_.Name例如

或者是什么样?

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

当然,你是对的。我的露营地大部分都是活跃的 - 所以即使99%的价值仍然是1。但是,有时我想通过一个(不同的)位字段来订购,例如首先是所有具有特定属性的营地,然后是其他营地。从我现在了解的情况来看,我需要使用第二个ORDER BY标准。 – Oliver 2010-06-01 21:18:49

3

您希望得到的结果按名称太订购,但只有IsActive在ORDER BY子句。

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

+0

谢谢你的回答,devio。好,你提到基于SET的BC,现在很有意义的是,ORDER BY 返回结果的不可预知的顺序(当然,在每个值内)。 – Oliver 2010-06-02 12:30:19

相关问题