2016-12-27 4 views
1

У меня есть канонический топ-N запрос к базе данных Oracle предложил все часто задаваемые вопросы и HowTos:заказать по rownum - это правильно или нет?

select ... from (
    select ... from ... order by ... 
) where ronwum <= N 

Он отлично работает на Oracle 11, то она возвращает топ-N записей в порядке, указанном в внутренний выбор.

Однако он ломается на Oracle 12. Он по-прежнему возвращает одни и те же записи верхнего уровня, но их можно перетасовать. Окончательный порядок этих записей не является детерминированным.

Я googled, но не нашел никаких связанных дискуссий. Похоже, что все остальные всегда получают правильный порядок записи от такого выбора.

Одно открытие было интересным, хотя. Я видел, что некоторые люди используют (без объяснения, к сожалению) дополнительное order by rownum положения во внешнем выберите:

select ... from (
    select ... from ... order by ... 
) where ronwum <= N 
order by rownum 

(как ROWNUM здесь есть ссылки на псевдостолбец Oracle, это не что-то возвращаемое внутреннего выбор)

Он работает, работает. Но с оптимизатором Oracle вы никогда не можете быть уверены, что это просто удача или действительно правильное решение.

Вопрос: order by rownum Гарантия правильного заказа в этом случае или нет, и почему? Я и мои коллеги не могли договориться об этом.

P.S. Я знаю о других способах выбора записей верхнего уровня, например. используя аналитическую функцию row_number и предложение fetch first, представленное в Oracle 12. Я также знаю, что я могу повторить то же самое order by ... на внешнем select. Вопрос только в order by rownum - это правильно или нет.

+3

Я думаю, что вам нужно переименовать 'rownum' на что-то другое во внутреннем select, иначе внешняя ссылка ссылается на rownum для внешнего запроса, а не на внутренний запрос. –

+1

Правильный способ сделать это - упорядочить по тем же выражениям во внешнем запросе, что и в подзапросе. Даже в Oracle 11 и ранее тот факт, что заказ был сохранен от внутреннего запроса до внешнего, был случайностью реализации - он не гарантируется стандартом SQL. – mathguy

ответ

-1

Внутренний запрос и внешний запрос могут или не могут дать другой порядок и, следовательно, различный порядок rownum. Поскольку rownum уже заказан, и если вы хотите получить верхние N записей, лучше всего создать псевдоним rownum во внутреннем запросе и использовать его во внешнем запросе.

... выберите из ( выберите RowNum р-н ... от ... ) где гп < = N порядка по гп

+1

Это не сработает, потому что rownum назначается перед заказом. Этот запрос даст N полностью случайных строк. И переписывание запроса не было вопросом. – Alexey