Значения ROWNUM присваиваются строкам по мере их возврата из запроса (или подзапроса).Если строка не возвращается, ей вообще не присваивается значение ROWNUM;поэтому возвращаемые значения ROWNUM всегда начинаются с 1 и увеличиваются на 1 для каждой строки.
(Обратите внимание, что эти значения присваиваются перед любой сортировкой, указанной в предложении ORDER BY
. Именно поэтому в вашем случае вам нужночтобы проверить rownum вне подзапроса.)
Странный логический элемент, который вы должны понимать, заключается в том, что когда у вас есть предикат для ROWNUM, вы фильтруете значение, которое будет существовать, только если строка проходит фильтр.Концептуально Oracle сначала применяет любые другие фильтры в запросе, а затем предварительно назначает ROWNUM 1 первой соответствующей строке и проверяет его на соответствие фильтру в ROWNUM.Если он пройдет эту проверку, он будет возвращен с этим значением ROWNUM, и следующей строке будет предварительно назначен ROWNUM 2. Но если он не пройдет проверку, строка будет отброшена, и то же значение ROWNUM предварительно назначеноследующая строка.
Поэтому, если фильтр в ROWNUM не принимает значение 1, никакие строки никогда не пропустят фильтр.
Использование аналитической функции ROW_NUMBER()
, показанной вдругие ответы - один из способов обойти это.Эта функция явно назначает номера строк (отличные от ROWNUM) на основе заданного порядка.Однако это может существенно изменить производительность, так как оптимизатор не обязательно понимает, что он может избежать назначения номеров для любой возможной строки для выполнения запроса.
Традиционный способ, основанный на ROWNUM, выполнять то, что вам нужно,:
SELECT id
FROM (
SELECT rownum rn, id
FROM (
SELECT id
FROM table
WHERE
PROCS_DT is null
ORDER BY prty desc, cret_dt
) where rownum <=200
) where rn > 101
Самый внутренний запрос концептуально находит все совпадающие строки и сортирует их.Следующий уровень присваивает им ROWNUM и возвращает только первые 200 совпадений.(И действительно, оптимизатор Oracle понимает важность сортировки, за которой следует фильтр ROWNUM, и обычно выполняет сортировку таким образом, чтобы идентифицировать первые 200 строк, не заботясь об определенном порядке других строк.)
Средний уровень также принимает ROWNUM, которые он назначает, и возвращает их как часть своего набора результатов с псевдонимом "rn".Это позволяет внешнему слою фильтровать это значение для установления нижнего предела.
Я бы поэкспериментировал с этим вариантом и аналитической функцией, чтобы увидеть, какая из них работает лучше.