Выбор второй строки таблицы с помощью rownum

Я пробовал следующий запрос:

select empno from (
                   select empno 
                     from emp
                    order by sal desc
                  )
where rownum = 2

Это не возвращает никаких записей.

Когда я попробовал этот запрос

 select rownum,empno from (
                        select empno from emp order by sal desc) 

Это дает мне этот вывод:

ROWNUM  EMPNO      
1       7802        
2       7809    
3       7813    
4       7823

Может ли кто-нибудь сказать мне, в чем проблема с моим первым запросом? Почему он не возвращает никаких записей, когда я добавляю фильтр ROWNUM?


person Gaurav Soni    schedule 11.02.2012    source источник


Ответы (9)


Чтобы объяснить такое поведение, нам нужно понять, как Oracle обрабатывает ROWNUM. При присвоении ROWNUM строке Oracle начинает с 1 и увеличивает значение только при выборе строки; то есть, когда все условия в предложении WHERE выполнены. Поскольку наше условие требует, чтобы ROWNUM было больше 2, никакие строки не выбираются, и ROWNUM никогда не увеличивается больше 1.

Суть в том, что условия, подобные приведенным ниже, будут работать должным образом.

.. ГДЕ ряд = 1;

.. ГДЕ rownum ‹= 10;

Хотя запросы с этими условиями всегда будут возвращать нулевые строки.

..ГДЕ ряд = 2;

.. ГДЕ rownum > 10;

Цитата из Понимание Oracle rownum

Вы должны изменить свой запрос таким образом, чтобы работать:

select empno
from
    (
    select empno, rownum as rn 
    from (
          select empno
          from emp
          order by sal desc
          )
    )
where rn=2;

EDIT: я исправил запрос, чтобы получить номер строки после порядка по описанию сал

person Florin Ghita    schedule 11.02.2012
comment
: Спасибо за объяснение +1 ... запрос не стоит, потому что я хочу, чтобы номер строки записей извлекался на основе порядка с помощью sal desc, запрос не будет работать, если мы поместим номер строки во внутренний запрос, он даст нам rownum записей таблицы emp, а не отсортированных данных.... Спасибо за объяснение - person Gaurav Soni; 11.02.2012
comment
Хороший ответ (+1), но предложенный вами запрос не будет работать правильно и вернет 2-го самого высокооплачиваемого сотрудника. Вам понадобится еще один уровень подзапроса, чтобы убедиться, что ROWNUM назначен после ORDER BY. - person Branko Dimitrijevic; 11.02.2012
comment
В качестве небольшого улучшения вы можете сократить средний запрос до rownum ‹= 2. Это, вероятно, улучшит производительность, когда таблица большая. Одна проблема, однако, заключается в том, что мы все еще не находим сотрудника со второй по величине зарплатой. Если есть два лучших сотрудника с одинаковой зарплатой, мы, по сути, выбираем одного произвольно... Если мы действительно хотим, чтобы сотрудники со второй по величине зарплатой должны выполнить запрос, который заказывает разные зарплаты... - person user6856; 10.02.2015
comment
@ user6856 Oracle всегда оптимизирует запросы такого типа. Предложенный мной запрос просканирует таблицу emp только один раз и при сканировании в памяти останется только две строки, те, у которых самая высокая зарплата. - person Florin Ghita; 11.02.2015
comment
@FlorinGhita Вот почему оракулу платят большие деньги. Они хороши в оптимизации. Иногда на самом деле попытка оптимизировать запрос делает оракул медленнее, потому что делает запрос слишком сложным для автоматической оптимизации. - person user6856; 13.02.2015

В первом запросе первая строка будет иметь ROWNUM = 1, поэтому будет отклонена. Вторая строка также будет иметь ROWNUM = 1 (поскольку предыдущая строка была отклонена) и также будет отклонена, третья строка также будет иметь ROWNUM = 1 (поскольку все строки до нее были отклонены), а также будет отклонена и т. д. Сеть результатом является то, что все строки отклоняются.

Второй запрос не должен возвращать полученный результат. Он должен правильно назначать ROWNUM после ORDER BY.

Как следствие всего этого нужно использовать не 2, а 3 уровня подзапросов, вот так:

SELECT EMPNO, SAL FROM ( -- Make sure row is not rejected before next ROWNUM can be assigned.
    SELECT EMPNO, SAL, ROWNUM R FROM ( -- Make sure ROWNUM is assigned after ORDER BY.
        SELECT EMPNO, SAL
        FROM EMP
        ORDER BY SAL DESC
    )
)
WHERE R = 2

Результат:

EMPNO                  SAL                    
---------------------- ---------------------- 
3                      7813                   
person Branko Dimitrijevic    schedule 11.02.2012
comment
Питти, это становится намного сложнее при выборе * вместо этого, если вы не хотите, чтобы rownum был частью вывода. Особенно при выполнении соединения или запроса представления. - person user6856; 10.02.2015

попробуй это:

SELECT ROW_NUMBER() OVER (ORDER BY empno) AS RowNum,
       empno
FROM   tableName
WHERE  RowNumber = 2;

Фрагмент из источника:

SELECT last_name FROM 
      (SELECT last_name, ROW_NUMBER() OVER (ORDER BY last_name) R FROM employees)
WHERE R BETWEEN 51 and 100

ССЫЛКА

person John Woo    schedule 11.02.2012
comment
: Спасибо за решение, но я не ищу здесь решения, я ищу причину, по которой приведенный выше запрос не работает. - person Gaurav Soni; 11.02.2012
comment
Считайте, что в вашем предложении where должно быть RowNum вместо RowNumber - person mahi_0707; 13.04.2016

Для n-й строки с использованием rownum в оракуле:

select * from TEST WHERE ROWNUM<=n
MINUS
select * from TEST WHERE ROWNUM<=(n-1);

Пример для второй строки:

select * from TEST WHERE ROWNUM<=2
MINUS
select * from TEST WHERE ROWNUM<=1;
person Md. Kamruzzaman    schedule 09.05.2017
comment
Камруззаман: Должны быть критерии для получения n-й записи, например, для второй по величине зарплаты, в вашем запросе нет такой логики. - person Gaurav Soni; 09.05.2017

выберите empno from(
выберите empno,rownum as rum
from emp,
упорядочьте по описанию sal
)
где rum=2;

person Deepak R    schedule 07.07.2015
comment
Привет, Дипак, и добро пожаловать в SO! Хотя ваш ответ может быть правильным, какова дополнительная ценность по сравнению с уже принятым ответом? Имхо, ваш ответ излишен и не добавляет никакой полезной информации. Таким образом, маловероятно, что он получит какое-либо положительное подтверждение. Сосредоточьтесь на оставшихся без ответа вопросах или добавляйте ответы с дополнительной ценностью, чтобы получить некоторую репутацию. - person cfi; 07.07.2015

Выберите вторую строку из таблицы в Oracle

SELECT *
FROM (SELECT * FROM emp ORDER BY rownum DESC)
WHERE rownum=1
person Nasir Uddin    schedule 09.12.2019

попробуй так работает 100% SQL› SELECT * FROM STUD;

НОМЕР ИМЯ ЗНАКИ


   104 mahesh                       85
   101 DHANU                        20
   102 BHARATH                      10
   100 RAJ                          50
   103 GOPI                         65

SQL> выберите * из (выберите MARKS,ROWNUM AS RS из ( выберите * из порядка стадий по меткам desc)) где RS=2;

 MARKS         RS

    65          2

SQL›

person Deshaboina Raju    schedule 22.10.2020

Вы можете использовать RANK или DENSE_RANK для достижения того, чего вы пытаетесь достичь здесь.

person ash    schedule 10.05.2016
comment
вы должны привести пример - person Austin; 10.05.2016

Попробуйте этот запрос на 100% работает

Выберите * из (выберите rownum как rn, emp.* from emp) Где rn=2;

person Pramod Tanwar    schedule 29.03.2021