Jak wybrać tylko 1 wiersz z Oracle sql?


111

Chcę użyć składni Oracle, aby wybrać tylko 1 wiersz z tabeli DUAL. Na przykład chcę wykonać to zapytanie:

SELECT user 
  FROM DUAL

... i miałoby około 40 płyt. Ale potrzebuję tylko jednej płyty. ... ORAZ chcę, aby stało się to bez WHEREklauzuli.

Potrzebuję czegoś w polu nazwa_tabeli, na przykład:

SELECT FirstRow(user) 
  FROM DUAL

1
Jaka wersja Oracle? Używanie ROWNUM lub ROW_NUMBER (9i +) oznaczałoby potrzebę zastosowania klauzuli WHERE
kucyki OMG

1
Czy nazwałeś stół dual?
ypercubeᵀᴹ

1
@ypercube dualto tabela systemowa w oracle

4
@Ben, naprawdę nie powinieneś tworzyć tabeli o nazwie DUAL. To trochę jak #define TRUE 0w C - jasne, może ci się udać, ale przyszli programiści cię nienawidzą.
Jeffrey Kemp,

3
Czy naprawdę próbowałeś biegać select user from dual? Jeśli nie, spróbuj tego i zobacz, co otrzymasz. W standardowym systemie Oracle odzyskasz użytkownika, z którym wykonujesz polecenie.
Shannon Severance,

Odpowiedzi:


170

Używasz ROWNUM.

to znaczy.

SELECT user FROM Dual WHERE ROWNUM = 1

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


O ile wiem, @ypercube tak. (Przynajmniej działa dla mojej instalacji oracle10g.)

@bdares: zadziała, tak. Ale nie twoja odpowiedź, z order by.
ypercubeᵀᴹ

1
Tak. ROWNUM to specjalna kolumna, która jest dodawana do zestawu wyników z wyliczeniem wyników. Możesz go również użyć do wybrania wielu, na przykład, jeśli chcesz znaleźć 10 najlepiej opłacanych pracowników, możesz powiedzieć „WYBIERZ użytkownika z pracowników GDZIE ROWNUM <= 10 ZAMÓWIENIE W ZALEŻNOŚCI OD PŁATNOŚCI”
mindvirus

10
@mkdess: nie, ORDER BYjest stosowane po WHERE.
ypercubeᵀᴹ

15
SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
Potrzebowałbyś

49

Znalazłem to „rozwiązanie” ukryte w jednym z komentarzy. Ponieważ szukałem tego przez jakiś czas, chciałbym to trochę podkreślić (nie mogę jeszcze komentować ani robić takich rzeczy ...), więc użyłem:

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

Spowoduje to wydrukowanie żądanego wpisu [Kolumna] z najnowszego wpisu w tabeli, przy założeniu, że [Data] jest zawsze wstawiana za pośrednictwem SYSDATE.


Okazało się, że zadziała również, jeśli złożysz zamówienie przez ROWID, o ile nigdy nie usuniesz żadnych rekordów i zawsze dbasz o ostatnią wstawioną / zmodyfikowaną.
vapcguy

@vapcguy: Nie oczekuj, że ROWID zostanie zamówiony, nawet jeśli nigdy nie usuniesz wiersza z tabeli! Nawet jeśli teraz zadziała, nigdy nie ma gwarancji, że będzie działać w przyszłych wersjach.
D. Mika

@ D.Mika Właściwie, jeśli teraz działa i nigdy nie dodajesz / usuwasz / aktualizujesz / usuwasz rekordów, nigdy nie powinno być żadnych problemów. Rekordy można zmienić tylko wtedy, gdy faktycznie je zmienisz. Istnieje błędne przekonanie, że w jakiś sposób ROWIDjest losowo modyfikowane przez Oracle. Tak nie jest. Polega ona na faktycznym modyfikowaniu wierszy, tj. Usuwasz jeden, a następnie wstawiasz. Wstawiony otrzyma stary ROWID. Istnieją takie rzeczy, jak statyczne tabele, które nigdy nie są aktualizowane - dobrym przykładem są stany w USA - gdzie gdyby się zmieniły, i tak prawdopodobnie miałoby to inne reperkusje, kiedy jest to w porządku.
vapcguy

@vapcguy: Cóż, prawie tak. Ale są inne operacje, które zmienią ROWID. A jeśli z jakiegoś powodu wyeksportujesz / zaimportujesz tabelę? Są inne operacje, ale niektóre z nich wymagają WŁĄCZENIA RUCHU WIERSZY. Chcę tylko powiedzieć, że poleganie na szczegółach implementacji, które mogą ulec zmianie w przyszłości, nie jest dobrym pomysłem.
D. Mika

@ D.Mika Jestem pewien, że jeśli są jakieś operacje, w których ROWIDmożna by je zmienić, dobry DBA wyszukałby je i zrobił, co mógł, aby ich uniknąć, gdyby istniała możliwość, że wpływają na tak statyczną tabelę, jak to opisałem tylko aplikacja powinna działać. SELECTZamiast tego można dokonać eksportu tabeli za pomocą instrukcji. Import miałby nastąpić raz i nigdy więcej. Rozumiem, ostrożność jest zdecydowanie potrzebna, ale problemy nie są nieuniknione.
vapcguy

35

Ta składnia jest dostępna w 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;

^^ Chciałem tylko zademonstrować, że można użyć wiersza lub wierszy (liczba mnoga), niezależnie od liczby żądanej liczby wierszy).


1
wybierz * z some_table pobierz tylko pierwszy 1 wiersz; jego nie działa w moim devloper swl ani w sql plus, więc błąd podczas pobierania.
nikhil sugandh

Czy używasz Oracle 12c?
mancini0

Naprawdę nie wiem, ale kiedy go otwieram, pokazuje to następująco: SQL * PLus wydanie 10.1.0.4.2 czy to nie jest 12 c
nikhil sugandh

dobrze - prawdopodobnie używasz wersji 10.1.xxx, możesz WYBRAĆ * FROM V $ VERSION
mancini0

10

mamy 3 możliwości uzyskania pierwszego wiersza w tabeli Oracle DB.

1) select * from table_name where rownum= 1jest najlepszym sposobem

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

Dzięki za odpowiedzi: w punkcie 3) „nowrum = 1” powinno prawdopodobnie zostać zmienione na „rownum = 1”.
Andre Nel

7

O ile wiem, dualtabela w Oracle to specjalna tabela z tylko jednym wierszem. Więc to wystarczyłoby:

SELECT user
FROM dual

to nieprawda, wybierz użytkownika z dual powinien dać ci wszystkich użytkowników
Ben

Tak też dzieje się w przypadku Wikipedii w Oracle
ypercubeᵀᴹ

1
.. i właśnie wypróbowałem na moim systemie, działa jak ypercube i cała powiązana dokumentacja wspomina. @Ben
Sathyajith Bhat

1
@Ben dual nie jest widokiem katalogu, nie pokaże „wszystkich użytkowników”. Do tego celu użyjesz widoku takiego jak ALL_USERS.
makrom

7

👌 Odpowiedź brzmi:

Zapytania zagnieżdżonego należy używać jako:

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

=> W PL / SQL „ROWNUM = 1” NIE jest równe „TOP 1” TSQL.

Nie możesz więc użyć takiego zapytania: "wybierz * z any_table_x, gdzie rownum = 1 zamówienie według any_column_x;" Ponieważ oracle otrzymuje pierwszy wiersz, a następnie stosuje kolejność po klauzuli.


1
Proszę o wyjaśnienie swojej odpowiedzi
hgwhittle

Należy unikać nietypowej składni bez ważnego powodu. W takim przypadku pomocne byłoby podanie przypadku testowego lub numeru błędu. Mglisto przypominam sobie kilka dziwnych problemów z rownum = 1, ale nie powinniśmy już pozwalać starym błędom wpływać na nasz kod.
Jon Heller,

7
@hgwhittle, Powodem, dla którego Fuat jest poprawny, jest to, że ROWNUM nie dba o „porządkowanie według”, po prostu pobiera pierwszy rekord, jaki może znaleźć i natychmiast go zwraca. Innymi słowy, kwalifikator ROWNUM nie ma żadnego szacunku dla polecenia „Order By”. Chciałbym, żeby tak nie było, ale Fuat ma rację, aby użyć zagnieżdżonego zapytania.
Eric Milliot-Martinez

5

W limit 1Oracle nie ma warunku (to jest MySQL / PostgresSQL), musisz to określić where rownum = 1.


5

„FirstRow” jest ograniczeniem i dlatego znajduje się w whereklauzuli, a nie w selectklauzuli. Nazywa się rownum

select * from dual where rownum = 1;

1
Zauważ, że nie zadziała to zgodnie z oczekiwaniami w połączeniu z ORDER BY, ponieważ porządkowanie następuje tylko po klauzuli where. Innymi słowy, aby znaleźć się na szczycie pewnego posortowanego zapytania, rownum jest całkowicie bezużyteczne.
Nyerguds

@Nyerguds, to tylko połowa prawdy. Możesz użyć order by before the Wherez zapytaniem View.
gdoron wspiera Monikę

4
Co z tego SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Cóż, to może działać, ale wygląda całkiem głupio, tbh.
Nyerguds

2

Jeśli jakikolwiek wiersz wystarczy, spróbuj:

select max(user)  
from table;

Brak klauzuli gdzie.


9
Z pewnością zajmie ci to tylko kilka sekund, aby wypróbować to sam
Matt Donnan,

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

będzie działać najlepiej, inna opcja to:

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

w scenariuszach, w których chcesz różnych podzbiorów, ale myślę, że możesz również użyć RANK()Ale, podoba mi się też, row_number() over(...)ponieważ nie jest wymagane grupowanie.


0

Jeśli chcesz odzyskać tylko pierwszy wiersz posortowanego wyniku z najmniejszą liczbą podzapytań, spróbuj tego:

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

Gdzie sysdate_col byłaby nazwą dowolnej kolumny, według której chcesz sortować, i oczywiście nazwa_tabeli byłaby nazwą tabeli, z której mają pochodzić posortowane dane.
Jody Fedor

-1

Bardziej elastyczny niż select max()jest:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.