我在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()表达式中的工作方式不同?
答案 0 :(得分:5)
ORDER BY this_.IsActive / * a bit field * /
因为那是一个位字段,它只能是0或1 ...我假设你有很多行,这个位字段为0或1排序它没有意义,如果90%是活跃的。 ..在这种情况下你没有真正订购,因为你没有第二次订购。
为什么不挑选一些独特的东西...也许是his_.Name例如
或者这个怎么样?
ROW_NUMBER() OVER (ORDER BY this_.IsActive, this_.Name)
答案 1 :(得分:3)
在两个实例中它基本上是随机的,因为位字段对于任何排序都是不好的(正如SQL Menace所指出的那样)。它们由数据库引擎单独评估,因为它们彼此无关。
注意:
答案 2 :(得分:3)
您希望结果也按名称排序,但在ORDER BY子句中只有IsActive。
SELECT的本质是基于集合的,因此如果您没有明确定义订单,则不应依赖查询的任意(但看似正确)有序结果。