Як вибрати лише 1 рядок з Oracle sql?


110

Я хочу використовувати синтаксис 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 ви повернете користувача, з яким виконуєте команду.
Шеннон Северанс

Відповіді:


169

Ви використовуєте 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 найоплачуваніших співробітників, ви можете сказати "ВИБРАТИ користувача з працівників, де
БЕЗ РОЗНУМУ

10
@mkdess: Ні, ORDER BYзастосовується після WHERE.
ypercubeᵀᴹ

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

49

Я знайшов це «рішення» прихованим в одному з коментарів. Оскільки я деякий час переглядав це, я хотів би трохи підкреслити його (ще не можу коментувати чи робити такі речі ...), тож ось що я використав:

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

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


Я виявив, що це також спрацює, якщо ви замовляєте до ROWIDтих пір, поки ви ніколи не видаляєте жодних записів і завжди дбаєте про останній вставлений / змінений.
vapcguy

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

@ D.Mika Насправді, якщо вона працює зараз, і ви ніколи не додаєте / видаляєте / не оновлюєте / не видаляєте записи, ніколи не повинно виникнути жодних проблем. Записи можна змінювати, лише якщо ви їх фактично змінюєте. Існує ця помилка, яка якось ROWIDвипадково модифікується Oracle. Це не так. Він заснований на фактичній модифікації рядків, тобто ви видаляєте один, а потім вставляєте. Вставлений отримає старий ROWID. Є такі речі, як статичні таблиці, які ніколи не оновлюються, як штати в США, є хорошим прикладом - де, якби це змінилося, воно, ймовірно, матиме інші наслідки, все одно, коли це добре.
vapcguy

@vapcguy: Ну, це майже правильно. Але є й інші операції, які змінять ROWID. Що робити, якщо ви чомусь експортуєте / імпортуєте таблицю? Є й інші операції, але деякі з них потребують РІЗНОГО РУХУВАННЯ. Я просто хочу сказати, що не варто покладатися на деталі реалізації, які можуть змінитися в майбутньому.
Д. Міка

@ D.Mika Я впевнений, що якщо є якісь операції, де ROWIDможна змінити, хороший DBA перегляне їх і зробить все можливе, щоб їх уникнути, якби була можливість вони впливають на таку статичну таблицю, як я описав, що тільки програма повинна працювати на. Експорт таблиці може бути зроблений 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
виберіть * з файлу some_table лише для першого ряду; він не працює в моєму swl devloper, ні в sql плюс помилка при виборі.
nikhil sugandh

Ви використовуєте oracle 12c?
mancini0

я дійсно не знаю, але коли я відкриваю, це показує так: SQL * PLus Release 10.1.0.4.2 - це не 12 с
nikhil sugandh

правильно - ви використовуєте ймовірність використання версії 10.1.xxx, ви можете ВИБІРАТИ * ВІД V $ VERSION
mancini0

10

у нас є 3 варіанти, щоб отримати перший рядок у таблиці DB Oracle.

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

це неправда. Вибір користувача з dual повинен дати вам усіх користувачів
Ben


1
.. і щойно випробуваний у моїй системі, працює як згадування ypercube та вся відповідна документація. @Ben
Сатьяджит Бхат

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.

Отже, ви не можете використовувати такий запит: "select * from any_table_x where rownum = 1 order by any_column_x;" Тому що оракул отримує перший рядок, тоді застосовується порядок за пунктом.


1
Додайте трохи пояснень у свою відповідь
hgwhittle

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

7
@hgwhittle, Причина, чому Fuat є правильним, полягає в тому, що ROWNUM не переймається "замовленням", він просто бере перший запис, який він може знайти, і негайно повертає його. Іншими словами, класифікатор ROWNUM не поважає команди "Порядок за". Я хочу, щоб це було не так, але Fuat правильно, щоб використовувати вкладений запит.
Ерік Мілліот-Мартінес

5

У limit 1Oracle немає жодної умови (це MySQL / PostgresSQL), вам потрібно вказати where rownum = 1.


5

"FirstRow" - це обмеження, і для цього йому місце в whereпункті, а не в selectпункті. І називається роундум

select * from dual where rownum = 1;

1
Зауважте, що це не буде працювати так, як очікувалося в поєднанні з ORDER BY, оскільки замовлення відбувається лише після пункту де. Іншими словами, щоб отримати вершину певного відсортованого запиту, 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 було б ім'ям будь-якого стовпця, за яким ви хочете впорядкувати, і, звичайно, ім'я_матеріали буде іменем таблиці, з якої ви хочете відсортувати дані.
Джоді Федір

-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.