Как мне попасть в топ-1 в Oracle?

Как мне сделать следующее?

select top 1 Fname from MyTbl

В Oracle 11g?


person Gold    schedule 10.08.2010    source источник
comment
Взгляните на Как выбрать TOP N строк из таблицы   -  person del.ave    schedule 10.08.2010
comment
возможный дубликат Как ограничить количество строк, возвращаемых запросом Oracle после заказа?   -  person Dave Jarvis    schedule 20.08.2013
comment
Можете ли вы сказать нам, в каком порядке вы хотите попасть в топ-1?   -  person Andrew Wolfe    schedule 26.11.2014
comment
Прежде всего, никогда не следует полагаться на движок БД для этого. Если вы хотите знать такие вещи, поставьте секвенсор. Когда вы это сделаете, они будут пронумерованы в том порядке, в котором они были вставлены.   -  person FlyingGuy    schedule 09.02.2015
comment
Очень полезный материал по этой теме use-the-index- luke.com/sql/partial-results/top-n-queries   -  person Ilia Maskov    schedule 28.10.2015
comment
Все повторяющиеся вопросы не помогают. Это фиктивный оракул!   -  person technazi    schedule 04.10.2018


Ответы (8)


Если вам нужна только первая выбранная строка, вы можете:

select fname from MyTbl where rownum = 1

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

select max(fname) over (rank() order by some_factor) from MyTbl
person mcpeterson    schedule 10.08.2010
comment
Это хорошо, если вам нужна только одна строка, и вам все равно, какая. Если вам нужны определенные строки, такие как самая последняя запись, вам нужно выполнить сортировку в подзапросе, например, в ответе Вэша. Oracle назначает rownums перед сортировкой. - person Scott Bailey; 10.08.2010
comment
@ Скотт Ага. это правильно. И Патрик, хороший момент, я думаю, что синтаксис здесь неправильный. Это действительно должно быть продолжение (density_rank () last ...) - person mcpeterson; 11.08.2010
comment
Разница между первым и вторым примером заключается в том, что первый выбирает строку A (любую строку, без порядка). Второй пример получает значение первой строки без выполнения внутреннего запроса порядка (как в примерах ниже). - person JulesLt; 12.08.2010
comment
Синтаксис неверен в: select max (fname) over (rank () order by some_factor) из MyTbl - person Stéphane Gerber; 06.11.2013
comment
Впечатлен аналитической функцией, не очень известной функциональностью Oracle - person jclozano; 26.02.2015
comment
@jclozano - не очень известная функциональность оракула. ​​С уважением, я позволю себе не согласиться. Это имеет значение, потому что малоизвестная функциональность имеет тенденцию подразумевать неясность и, следовательно, может указывать на то, что нам следует избегать использования. Это не является непонятным, и его использования не следует избегать. - person Sepster; 18.03.2015
comment
@Sepster, я согласен, что этого не следует избегать, просто по моему опыту я не встречал много людей, которые действительно знают об этой функции - person jclozano; 18.03.2015
comment
Второй запрос должен быть select max(fname) keep (dense_rank first order by some_factor ) from MyTbl. - person Barbaros Özhan; 14.07.2019

С помощью Oracle 12c (июнь 2013 г.) вы можете использовать его следующим образом.

SELECT * FROM   MYTABLE
--ORDER BY COLUMNNAME -OPTIONAL          
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
person MSK    schedule 27.04.2015
comment
Интересная команда, здесь я использую 12c, и OFFSET 0 ROWS, по-видимому, не нужен, вы можете использовать FETCH NEXT 1 ROWS ONLY или даже FETCH FIRST ROW ONLY, порядок важен, или это будет эквивалентно простому использованию WHERE rownum = 1. Я даже пробовал это в инструкции OUTER APPLY, и там она работала как функция TOP Ms-SQL. - person Rafael Merlin; 06.11.2015
comment
Вы правы, @RafaelMerlin. После вашего поста я понял, что OFFSET 0 ROWS не нужен. Это было бы полезно при извлечении данных между вершиной X и вершиной Y. - person MSK; 06.01.2016
comment
Дополнительные примеры: oracle-base.com / article / 12c / - person FixFaier; 05.01.2018
comment
Пока все хорошо, с одним важным упущенным моментом - TIES. Обратитесь к this для случаев, когда возникают связи для версий 12c + и 12c -. - person Barbaros Özhan; 14.07.2019

Вы можете использовать ROW_NUMBER() с предложением ORDER BY в подзапросе и использовать этот столбец вместо TOP N. Это можно объяснить пошагово.

См. Таблицу ниже, в которой есть два столбца NAME и DT_CREATED.

введите описание изображения здесь

Если вам нужно взять только первые две даты независимо от NAME, вы можете использовать запрос ниже. Логика написана внутри запроса

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
    -- Generates numbers in a column in sequence in the order of date
    SELECT ROW_NUMBER() OVER (ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

РЕЗУЛЬТАТ

введите здесь описание изображения

В некоторых ситуациях нам нужно выбрать TOP N результатов, соответствующих каждому NAME. В таком случае мы можем использовать PARTITION BY с предложением ORDER BY в подзапросе. Обратитесь к приведенному ниже запросу.

-- The number of records can be specified in WHERE clause
SELECT RNO,NAME,DT_CREATED
FROM
(
  --Generates numbers in a column in sequence in the order of date for each NAME
    SELECT ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY DT_CREATED) AS RNO,
    NAME,DT_CREATED
    FROM DEMOTOP
)TAB
WHERE RNO<3;

РЕЗУЛЬТАТ

введите здесь описание изображения

person Sarath KS    schedule 06.11.2015
comment
Использование ROW_NUMBER () ... более правильное решение, чем в ответе по теме. Одна проблема с этим решением (и с вариантом max (field) тоже), что вы не можете делать такие вещи, как select ... (select ROW_NUMBER () ...) для обновления; - person Alexo Po.; 09.12.2015
comment
И это иногда очень важно в PL / SQL (извините, не удалось отредактировать предыдущий комментарий за 5 минут). - person Alexo Po.; 09.12.2015
comment
В этом случае мы можем использовать CTE как во внешней части. Верно? @ Алексо По. - person Sarath KS; 09.12.2015
comment
Думаю, я вас не понимаю. Предложение для обновления может использоваться, когда ROWID легко сохраняется Oracle. Таким образом, группировка (и группировка из-за использования аналитического предложения) скрывает настоящий ROWID, и строки не могут быть заблокированы. Во-вторых, CTE (предложение with (select ... ) as ) ничего не меняет в этой проблеме, CTE просто нацелен на чтение и поддержку запросов. Верно? @Sarath Avanavu - person Alexo Po.; 11.12.2015
comment
Обратите внимание на себя. Проблема с ROWID на самом деле возникает именно из-за условия where RNO ‹3, в этом случае значение RNO не связано с ROWID, поэтому Oracle не может блокировать строки. - person Alexo Po.; 11.12.2015
comment
Более простое решение темы (без аналитических функций) приведено здесь: stackoverflow.com/questions/470542/ - person Alexo Po.; 11.12.2015

Вы можете сделать что-то вроде

    SELECT *
      FROM (SELECT Fname FROM MyTbl ORDER BY Fname )
 WHERE rownum = 1;

Вы также можете использовать аналитические функции RANK и / или DENSE_RANK, но, вероятно, самый простой вариант - ROWNUM.

person Sunil    schedule 09.12.2013
comment
не могли бы вы помочь с примером ранга и т. д. - person breakfreehg; 15.09.2014

Использовать:

SELECT x.*
  FROM (SELECT fname 
          FROM MyTbl) x
 WHERE ROWNUM = 1

Если вы используете Oracle9i +, вы можете посмотреть на аналитические функции, такие как ROW_NUMBER (), но они не будут работать так же хорошо, как ROWNUM.

person OMG Ponies    schedule 10.08.2010
comment
Хороший ответ, но с небольшой опечаткой. Где вы говорите, что Oracle9i + не должен быть 8i? download-west.oracle. com / docs / cd / A87860_01 / doc / server.817 / - person Ian Carpenter; 10.08.2010
comment
@carpenteri: Да, аналитика была доступна в 8i - не могу вспомнить подробностей, но аналитика не была доступна для публики до 9i. - person OMG Ponies; 10.08.2010
comment
Небольшой комментарий - ответ Vash ниже включает ORDER BY во внутреннем запросе, который имеет решающее значение, если вы хотите, чтобы значение Fname было TOP, а не 'first' (которое может быть любым, скорее всего, первой вставленной строкой). Может стоит отредактировать? - person JulesLt; 12.08.2010
comment
@JulesLt: запрос, предоставленный OP, не включает ORDER BY, поэтому этот ответ представляет собой точный перевод в синтаксис Oracle. - person OMG Ponies; 12.08.2010
comment
Мое непонимание синтаксиса SQL SERVER TOP (ошибочно предполагалось, что он похож на FIRST in RANK, а не на ROWNUM). Проголосовал. - person JulesLt; 12.08.2010
comment
@JulesLt: Не беспокойтесь, вероятно, часть того, почему TOP не был принят в качестве средства ANSI для ограничения набора результатов за пределами фильтрации. - person OMG Ponies; 12.08.2010
comment
@OMGPonies: аналитика была доступна в SQL, но не в PL/SQL в 8i. Вы должны были использовать EXECUTE IMMEDIATE, чтобы использовать их в блоке PL/SQL. - person Quassnoi; 08.09.2010
comment
@Quassnoi: А? Я думаю, что APC сказал, что аналитика доступна только в определенной версии 8i. Значит, динамический SQL обойдет оценку PLSQL? - person OMG Ponies; 08.09.2010
comment
@OMGPonies: 8 и 8i были разными версиями, и только последняя поддерживала аналитику (с R2, AFAIR). SQL и PL/SQL имели разные парсеры, процедурный не понимал аналитики и прочего. EXECUTE IMMEDIATE был проанализирован парсером SQL. Они были объединены в 9i. - person Quassnoi; 08.09.2010
comment
@OMGPonies: когда в 2000 году был выпущен 8i R2, у нас была встреча, на которой я настаивал на обновлении всех наших клиентов, использующих предыдущие версии (к тому времени более 200 установок), и прекращении поддержки 8. Разработчики в этой компании до сих пор считают это наиболее важным решением, поскольку следующий конец поддержки произошел только в 2009. - person Quassnoi; 08.09.2010
comment
@Quassnoi: Да, я вижу, что последовательный подход был бы лучше всего - как для разработки, так и для поддержки. Я не могу вспомнить, был ли это 8 или 8i, который мы использовали в школе, но мы определенно не использовали аналитику или динамический SQL. - person OMG Ponies; 09.09.2010

Выбрать первую строку из таблицы и выбрать одну строку из таблицы - это две разные задачи, и для них нужен другой запрос. Есть много способов сделать это. Четыре из них:

Первый

select  max(Fname) from MyTbl;

Второй

select  min(Fname) from MyTbl;

В третьих

select  Fname from MyTbl  where rownum = 1;

Четвертый

select  max(Fname) from MyTbl where rowid=(select  max(rowid) from MyTbl)
person Vikas Hardia    schedule 12.03.2014

У меня была такая же проблема, и я могу исправить это с помощью этого решения:

select a.*, rownum 
from (select Fname from MyTbl order by Fname DESC) a
where
rownum = 1

Вы можете упорядочить результат до того, как первое значение будет наверху.

Удачи

person user2607028    schedule 27.07.2013

person    schedule
comment
Этот ответ правильно попадает в верхнюю строку (упорядочивает результаты перед ограничением ROWNUM). - person JulesLt; 12.08.2010
comment
Этот ответ не является точным переводом - исходный запрос не имеет ORDER BY и не возвращает все столбцы в таблице. - person OMG Ponies; 12.08.2010
comment
Я исправился (см. Ниже). Поменяет голоса, когда время истечет. - person JulesLt; 12.08.2010
comment
@OMGPonies да. но это, вероятно, то, что на самом деле хочет большинство людей, которые приходят на эту страницу через поиск в Google своей проблемы. - person NimChimpsky; 19.11.2015
comment
Это наверняка лучший ответ в этой теме. Я мог бы добавить примечание, что для top X его можно изменить на WHERE ROWNUM <= X - person SomethingSomething; 21.02.2016
comment
у меня сработало! этот ответ правильно дает мне первую строку (упорядоченную по убыванию) - person Steven Ferrer; 13.06.2018