2010-06-01 2 views
3

Я работаю на SQL Server 2008, используя NHibernate в качестве уровня персистентности (хотя эта проблема, по-моему, является чисто SQL).Почему ROW_NUMBER OVER (ORDER BY column) возвращает другой порядок результата, чем только столбец 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 

Однако, если опустить 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()?

+0

странно, потому что для диалекта 2005 года столбец row_number всегда называется '__hibernate_sort_row', а порядок всегда использует этот столбец. – dotjoe

ответ

3

В обоих случаях это случайный случай, потому что бит-поле плохо для любого заказа (как отмечал SQL-угроза). Они отдельно оцениваются движком БД, потому что они не имеют ничего общего друг с другом.

Примечание:

  • Внутренний ORDER BY только относится к порядку величины ROW_NUMBER().
  • Вашего выхода ORDER BY является только this_.IsActive
+0

Спасибо за понимание. Это имеет смысл. Поэтому мой вопрос действительно должен быть: почему NHibernate делает это так? Должен ли я открыть для этого новый вопрос? – Oliver

+0

Я бы открыл новый вопрос. Это вопрос NHibernate, а не SQL. это странно, хотя если это то, что делает NHibernate, если только он не сортирует клиентскую сторону, используя новый столбец. Но это основной материал SQL, хотя в большинстве движков БД. – gbn

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

3

Вы ожидаете, что результат заказываются по имени тоже, но только IsActive в ORDER BY предложения.

Характер SELECT основан на наборе, поэтому вы не должны полагаться на произвольные (но, по-видимому, правильные) упорядоченные результаты вашего запроса, если вы явно не определяете порядок.

+0

Спасибо за ваш ответ devio. Хорошо, что вы упомянули SET-based, bc, теперь имеет смысл, что ORDER BY возвращает непредсказуемый порядок результатов (в пределах каждого значения, конечно). – Oliver

Смежные вопросы