Как выбрать только 1 строку из Oracle sql?


111

Я хочу использовать синтаксис Oracle, чтобы выбрать только 1 строку из таблицы DUAL . Например, я хочу выполнить такой запрос:

SELECT user 
  FROM DUAL

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

Мне нужно что-то в поле table_name, например:

SELECT FirstRow(user) 
  FROM DUAL

1
Какая версия Oracle? Использование ROWNUM или ROW_NUMBER (9i +) означало бы необходимость предложения WHERE
OMG Ponies,

1
Вы назвали стол dual?
ypercubeᵀᴹ

1
@ypercube dual- системная таблица в oracle

4
@Ben, вам действительно не следует создавать таблицу с именем DUAL. Это немного похоже #define TRUE 0на C - конечно, это может сработать для вас, но будущие разработчики будут вас ненавидеть.
Джеффри Кемп

3
Вы действительно пробовали бежать select user from dual? Если нет, попробуйте это и посмотрите, что у вас получится. В стандартной системе Oracle вы вернетесь пользователя, с которым выполняете команду.
Шеннон Северанс

Ответы:


170

Вы используете ROWNUM.

т.е.

SELECT user FROM Dual WHERE ROWNUM = 1

http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns009.htm


@ypercube, насколько я могу судить, это так. (По крайней мере, это работает для моей установки oracle10g.)

@bdares: будет работать, да. Но не ваш ответ с расширением order by.
ypercubeᵀᴹ

1
Да. ROWNUM - это специальный столбец, который добавляется к набору результатов и перечисляет результаты. Вы также можете использовать его, чтобы выбрать несколько, например, если вы хотите найти 10 самых высокооплачиваемых сотрудников, вы можете сказать: «ВЫБРАТЬ пользователя ИЗ СОТРУДНИКОВ, ГДЕ ROWNUM <= 10 ЗАКАЗАТЬ ПО УБЫТКУ ЗАПЛАТЫ»
mindvirus

10
@mkdess: Нет, ORDER BYприменяется после WHERE.
ypercubeᵀᴹ

15
Вам понадобится:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

50

Я нашел это "решение" спрятанным в одном из комментариев. Поскольку я некоторое время искал это, я хотел бы немного выделить его (пока не могу комментировать или делать такие вещи ...), поэтому я использовал следующее:

SELECT * FROM (SELECT [Column] FROM [Table] ORDER BY [Date] DESC) WHERE ROWNUM = 1

Это напечатает мне желаемую запись [Столбец] из самой новой записи в таблице, предполагая, что [Дата] всегда вставляется через SYSDATE.


Я обнаружил, что это также будет работать, если вы сделаете заказ ROWID, если вы никогда не удаляете какие-либо записи и всегда заботитесь о последней вставленной / измененной.
vapcguy 07

@vapcguy: Не ждите, что ROWID будет заказан, даже если вы никогда не удаляете строку из таблицы! Даже если это сработает для вас сейчас, никогда не будет гарантировано работать в будущих версиях.
Д. Мика

@ D.Mika На самом деле, если он работает сейчас, и вы никогда не добавляете / не удаляете / не обновляете / не удаляете записи, проблем быть не должно. Записи могут быть изменены только в том случае, если вы действительно их измените. Существует это заблуждение, которое каким-то образом ROWIDслучайно модифицируется Oracle. Это не так. Он основан на фактическом изменении строк, то есть вы удаляете одну, а затем вставляете ее. Вставленный получит старый ROWID. Есть такие вещи, как статические таблицы, которые никогда не обновляются, как в США, что является хорошим примером. Если бы они изменились, это, вероятно, имело бы другие последствия, в любом случае, когда это нормально.
vapcguy

@vapcguy: Ну, почти верно. Но есть и другие операции, которые изменят ROWID. Что делать, если вы по какой-то причине экспортируете / импортируете таблицу? Есть и другие операции, но для некоторых из них требуется РАЗРЕШЕНИЕ СТРОКИ. Я просто хочу сказать, что не стоит полагаться на детали реализации, которые могут измениться в будущем.
Д. Мика

@ D.Mika Я уверен, что если есть какие-либо операции, в которых ROWIDможно изменить, хороший администратор баз данных найдет их и сделает все возможное, чтобы избежать их, если бы существовала вероятность, что они влияют на такую ​​статическую таблицу, как я описал только приложение должно работать. SELECTВместо этого можно выполнить экспорт таблицы с помощью оператора. Импорт произойдет один раз, а потом никогда больше. Я понимаю, что забота определенно нужна, но проблемы далеко не неизбежны.
vapcguy

35

Этот синтаксис доступен в Oracle 12c:

select * from some_table fetch first 1 row only;
select * from some_table fetch first 1 rows only;
select * from some_table fetch first 10 row only;
select * from some_table fetch first 10 rows only;

^^ Я просто хотел продемонстрировать, что можно использовать строку или строки (во множественном числе) независимо от множества желаемого количества строк.)


1
select * from some_table извлечь только первую строку; он не работает ни в моем swl devloper, ни в sql plus, поэтому ошибка при выборке.
nikhil sugandh 09

Вы используете oracle 12c?
mancini0

я действительно не знаю, но когда я открываю его, это выглядит так: SQL * PLus Release 10.1.0.4.2 это не 12 c
nikhil sugandh

правильно - вы, вероятно, используете версию 10.1.xxx, вы можете ВЫБРАТЬ * ИЗ ВЕРСИИ V $
mancini0

10

у нас есть 3 варианта получения первой строки в таблице Oracle DB.

1) select * from table_name where rownum= 1 лучший способ

2) select * from table_name where id = ( select min(id) from table_name)

3)

select * from 
    (select * from table_name order by id)
where rownum = 1

Спасибо за ответы: в пункте 3) "nowrum = 1", вероятно, следует заменить на "rownum = 1".
Андре Нел

7

Насколько мне известно, dualтаблица в Oracle - это особая таблица с одной строкой. Итак, этого было бы достаточно:

SELECT user
FROM dual

это неправда, выбор пользователя из двойного должен дать вам всех пользователей
Бен,


1
.. и только что опробовал на моей системе, работает как ypercube и вся сопутствующая документация. @Ben
Sathyajith Bhat

1
@Ben dual - это не просмотр каталога, он не отображает «всех пользователей». Для этой цели вы должны использовать представление типа ALL_USERS.
макром

7

👌 Ответ:

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

SELECT *
FROM ANY_TABLE_X 
WHERE ANY_COLUMN_X = (SELECT MAX(ANY_COLUMN_X) FROM ANY_TABLE_X) 

=> В PL / SQL «ROWNUM = 1» НЕ равно «TOP 1» TSQL.

Таким образом, вы не можете использовать такой запрос: «выберите * из any_table_x, где rownum = 1 order by any_column_x;» Поскольку оракул получает первую строку, он применяет предложение order by.


1
Пожалуйста, добавьте пояснения к своему ответу
hgwhittle

Необычного синтаксиса следует избегать без уважительной причины. В этом случае было бы полезно указать либо тестовый пример, либо номер ошибки. Я смутно припоминаю некоторые странные проблемы с rownum = 1, но мы не должны больше позволять старым ошибкам влиять на наш код.
Джон Хеллер

7
@hgwhittle, Причина, по которой Fuat прав, в том, что ROWNUM не заботится о 'ordery by', он просто берет первую запись, которую может найти, и немедленно возвращает ее. Другими словами, квалификатор ROWNUM не учитывает команду «Упорядочить по». Я бы хотел, чтобы это было не так, но Фуат прав, если использовать вложенный запрос.
Эрик Миллиот-Мартинес,


5

"FirstRow" - это ограничение, поэтому его место в whereпредложении, а не в selectпредложении. И это называется rownum

select * from dual where rownum = 1;

1
Обратите внимание, что это не будет работать должным образом в сочетании с ORDER BY, поскольку упорядочение происходит только после предложения where. Другими словами, для получения вершины определенного отсортированного запроса rownum совершенно бесполезен.
Nyerguds

@Nyerguds, это правда только наполовину. Вы можете использовать заказ перед Whereс запросом просмотра.
gdoron поддерживает Монику

4
Что так SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Что ж, это может сработать, но выглядит довольно глупо, черт возьми.
Nyerguds

2

Если подойдет любая строка, попробуйте:

select max(user)  
from table;

Пункт не где.


9
Конечно, вам понадобится всего несколько секунд, чтобы попробовать это на себе,
Мэтт Доннан,

1
select name, price
  from (
    select name, price, 
    row_number() over (order by price) r
      from items
  )
where r between 1 and 5; 

1

select a.user from (select user from users order by user) a where rownum = 1

будет работать лучше всего, другой вариант:

select a.user 
from ( 
select user, 
row_number() over (order by user) user_rank, 
row_number() over (partition by dept order by user) user_dept_rank 
from users 
) a 
where a.user_rank = 1 or user_dept_rank = 2

в сценариях, где вам нужны разные подмножества, но я думаю, вы также можете использовать RANK()Но мне также нравится, row_number() over(...)поскольку группировка не требуется.


0

Если вы хотите вернуть только первую строку отсортированного результата с наименьшим количеством подзапросов, попробуйте следующее:

select *
  from ( select a.*
              , row_number() over ( order by sysdate_col desc ) as row_num
           from table_name a )
  where row_num = 1;

Где sysdate_col - это имя любого столбца, по которому вы хотите выполнить сортировку, и, конечно же, table_name - это имя таблицы, из которой должны поступать отсортированные данные.
Джоди Федор,

-1

Более гибкий, чем select max()есть:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.