Oracle Select query помогите пожалуйста - PullRequest
2 голосов
/ 21 июля 2011
SELECT  id
      FROM    ( 
 SELECT  id
      FROM   table      
      WHERE   
      PROCS_DT is null
      ORDER BY prty desc, cret_dt ) where rownum >0 and rownum <=100 

Приведенный выше запрос возвращает мне 100 записей, как и ожидалось

 SELECT  id
          FROM    ( 
     SELECT  id
          FROM   table      
          WHERE   
          PROCS_DT is null
          ORDER BY prty desc, cret_dt ) where rownum >101 and rownum <=200 

почему приведенный выше запрос возвращает ноль записей?

Может ли кто-нибудь помочь мне, как я могу продолжать. Я туп в оракуле ...

Ответы [ 2 ]

3 голосов
/ 21 июля 2011

Значения 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".Это позволяет внешнему слою фильтровать это значение для установления нижнего предела.

Я бы поэкспериментировал с этим вариантом и аналитической функцией, чтобы увидеть, какая из них работает лучше.

3 голосов
/ 21 июля 2011

Попробуйте:

SELECT id
FROM
  (SELECT id,
          rownum AS rn
   FROM
     (SELECT id
      FROM TABLE
      WHERE PROCS_DT IS NULL
      ORDER BY prty DESC, cret_dt) )
WHERE rn >101
  AND rn <=200

Если вам удобно использовать АНАЛИТИЧЕСКИЕ функции, попробуйте следующее:

SELECT id
  FROM 
    (
        SELECT id,
                ROW_NUMBER() OVER(ORDER BY prty DESC, cret_dt ) rn
            FROM table
        WHERE procs_dt IS NULL
    )
 WHERE rn >101 and rn <=200  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...