Come selezionare solo 1 riga da Oracle sql?


111

Voglio usare la sintassi Oracle per selezionare solo 1 riga dalla tabella DUAL. Ad esempio, voglio eseguire questa query:

SELECT user 
  FROM DUAL

... e avrebbe, tipo, 40 record. Ma ho bisogno di un solo record. ... E, voglio farlo accadere senza una WHEREclausola.

Ho bisogno di qualcosa nel campo table_name come:

SELECT FirstRow(user) 
  FROM DUAL

1
Quale versione di Oracle? Usare ROWNUM o ROW_NUMBER (9i +) significherebbe aver bisogno di una clausola WHERE
OMG Ponies

1
Hai nominato un tavolo dual?
ypercubeᵀᴹ

1
@ypercube dualè la tabella di sistema in Oracle

4
@ Ben, non dovresti davvero creare una tabella chiamata DUAL. È un po 'come #define TRUE 0in C - certo, potrebbe funzionare per te, ma i futuri sviluppatori ti odieranno.
Jeffrey Kemp

3
Hai davvero provato a correre select user from dual? In caso contrario, provalo e guarda cosa ottieni. Su un sistema Oracle standard, recupererai l'utente con cui stai eseguendo il comando.
Shannon Severance

Risposte:


170

Usi ROWNUM.

vale a dire.

SELECT user FROM Dual WHERE ROWNUM = 1

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


@ypercube per quanto ne so, lo fa. (Almeno funziona per la mia installazione di oracle10g.)

@bdares: funzionerà, sì. Ma non la tua risposta, con il order by.
ypercubeᵀᴹ

1
Sì. ROWNUM è una colonna speciale che viene aggiunta al set di risultati enumerando i risultati. Puoi usarlo anche per selezionare più dipendenti, ad esempio, se desideri trovare i 10 dipendenti più pagati, potresti dire "SELEZIONA utente DA Dipendenti WHERE ROWNUM <= 10 ORDER BY SALARY
DESCENDING

10
@mkdess: No, ORDER BYviene applicato dopo WHERE.
ypercubeᵀᴹ

15
Avresti bisogno di:SELECT * FROM (SELECT user FROM Employees ORDER BY SALARY DESC) WHERE ROWNUM <= 10
ypercubeᵀᴹ

49

Ho trovato questa "soluzione" nascosta in uno dei commenti. Dato che lo stavo cercando da un po ', vorrei evidenziarlo un po' (non posso ancora commentare o fare cose del genere ...), quindi questo è quello che ho usato:

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

Questo mi stamperà la voce [Colonna] desiderata dalla voce più recente nella tabella, assumendo che [Data] sia sempre inserita tramite SYSDATE.


Ho scoperto che funzionerà anche se ordini per ROWID, purché non elimini mai alcun record e ti preoccupi sempre dell'ultimo inserito / modificato.
vapcguy

@vapcguy: non aspettarti che ROWID venga ordinato, anche se non elimini mai una riga dalla tabella! Anche se funziona per te ora, non è mai garantito che funzioni nelle versioni future.
D. Mika

@ D.Mika In realtà, se ora funziona e non aggiungi / rimuovi / aggiorni / cancelli mai record, non dovrebbero mai esserci problemi. I record possono essere modificati solo se vengono effettivamente modificati. C'è questo malinteso che in qualche modo ROWIDviene modificato in modo casuale da Oracle. Non lo è. Si basa sulla modifica effettiva delle righe, ovvero si elimina una, quindi si inserisce una. Quello inserito otterrà quello vecchio ROWID. Ci sono cose come le tabelle statiche che non vengono mai aggiornate, come gli stati negli Stati Uniti sono un buon esempio, dove se cambiasse, probabilmente avrebbe altre ripercussioni, comunque, quando questo va bene.
vapcguy

@vapcguy: beh, è ​​quasi vero. Ma ci sono altre operazioni che cambieranno il ROWID. Cosa succede se esporti / importi la tabella per qualche motivo? Ci sono altre operazioni, ma alcune necessitano di ABILITA MOVIMENTO FILA. Voglio solo dire che non è una buona idea fare affidamento su un dettaglio di implementazione che potrebbe cambiare in futuro.
D. Mika

@ D.Mika Sono sicuro che se ci sono operazioni in cui ROWIDpotrebbero essere cambiate, un buon DBA le cercherebbe e farebbe il possibile per evitarle se ci fosse la possibilità che stessero influenzando una tabella così statica come ho descritto che solo l'applicazione dovrebbe funzionare. È invece possibile esportare una tabella con SELECTun'istruzione. L'importazione sarebbe avvenuta una volta e poi mai più. Ho capito il tuo punto, è assolutamente necessaria la cura, ma i problemi sono tutt'altro che inevitabili.
vapcguy

35

Questa sintassi è disponibile in 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;

^^ Volevo solo dimostrare che sia la riga che le righe (plurale) possono essere utilizzate indipendentemente dalla pluralità del numero di righe desiderato.)


1
seleziona * da some_table recupera solo la prima riga; non funziona nel mio swl devloper né in sql plus quindi errore durante il recupero.
nikhil sugandh

Stai usando Oracle 12c?
mancini0

Non lo so davvero, ma quando lo apro appare così: SQL * PLus Release 10.1.0.4.2 non è 12 c
nikhil sugandh

corretto - stai usando probabilmente la versione 10.1.xxx, puoi SELEZIONARE * DA V $ VERSION
mancini0

10

abbiamo 3 scelte per ottenere la prima riga nella tabella Oracle DB.

1) select * from table_name where rownum= 1è il modo migliore

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

Grazie per le risposte: al punto 3) "nowrum = 1" dovrebbe probabilmente essere cambiato in "rownum = 1".
Andre Nel

7

Per quanto ne so, la dualtabella in Oracle è una tabella speciale con una sola riga. Quindi, questo sarebbe sufficiente:

SELECT user
FROM dual

non è vero selezionare l'utente da dual dovrebbe darti tutti gli utenti
Ben


1
.. e appena provato sul mio sistema, funziona come ypercube e tutta la documentazione correlata menziona. @Ben
Sathyajith Bhat

1
@ Ben dual non è una visualizzazione del catalogo, non mostrerà "tutti gli utenti". A tale scopo utilizzeresti una vista come ALL_USERS.
dal

7

👌 La risposta è:

È necessario utilizzare query annidate come:

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

=> In PL / SQL "ROWNUM = 1" NON è uguale a "TOP 1" di TSQL.

Quindi non puoi usare una query come questa: "seleziona * da any_table_x dove rownum = 1 order by any_column_x;" Perché Oracle ottiene la prima riga, quindi applica l'ordine per clausola.


1
Per favore aggiungi qualche chiarimento alla tua risposta
hgwhittle

La sintassi insolita dovrebbe essere evitata senza una buona ragione. In questo caso, sarebbe utile fornire un test case o un numero di bug. Ricordo vagamente alcuni strani problemi con rownum = 1, ma non dovremmo più lasciare che vecchi bug influenzino il nostro codice.
Jon Heller

7
@hgwhittle, Il motivo per cui Fuat è corretto è perché ROWNUM non si preoccupa di "ordery by", si limita a prendere il primo record che riesce a trovare e lo restituisce immediatamente. Quindi, in altre parole, il qualificatore ROWNUM non ha alcun rispetto per il comando "Order By". Vorrei che non fosse così, ma Fuat ha ragione, per usare la query annidata.
Eric Milliot-Martinez

5

Non ci sono limit 1condizioni (questo è MySQL / PostgresSQL) in Oracle, è necessario specificarlo where rownum = 1.


5

"FirstRow" è una restrizione e quindi è posto nella whereclausola non nella selectclausola. E si chiama rownum

select * from dual where rownum = 1;

1
Nota che questo non funzionerà come previsto in combinazione con ORDER BY, poiché l'ordinamento avviene solo dopo la clausola where. In altre parole, per ottenere l'inizio di una determinata query ordinata, rownum è assolutamente inutile.
Nyerguds

@Nyerguds, questo è vero solo a metà. È possibile utilizzare order by prima di Wherecon una query di visualizzazione.
gdoron sostiene Monica il

4
Cosa, quindi SELECT * FROM (SELECT * FROM ... WHERE ... ORDER BY ...) WHERE ROWNUM = 1? Beh, potrebbe funzionare, ma sembra piuttosto stupido, tbh.
Nyerguds

2

Se una riga va bene, prova:

select max(user)  
from table;

Nessuna clausola dove.


9
Sicuramente ti serviranno solo pochi secondi per provarlo di persona
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

funzionerà al meglio, un'altra opzione è:

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

in scenari in cui desideri diversi sottoinsiemi, ma immagino che potresti anche usare RANK()Ma, mi piace anche row_number() over(...)perché non è richiesto alcun raggruppamento.


0

Se vuoi recuperare solo la prima riga di un risultato ordinato con il minor numero di sottoquery, prova questo:

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

Dove sysdate_col sarebbe il nome di qualsiasi colonna in base a cui si desidera ordinare e, naturalmente, table_name sarebbe il nome della tabella da cui si desidera che i dati ordinati provengano.
Jody Fedor

-1

Più flessibile di quanto non select max()sia:

select distinct first_row(column_x) over (order by column_y,column_z,...) from Table_A
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.