Recupera massimo registrazione / minimal
-
12-09-2019 - |
Domanda
Una query SQL piuttosto complicata su cui stavo lavorando mi ha fatto pensare a una limitazione di (ANSI) SQL:
C'è un modo per recuperare un record che è massima o minima rispetto ad un ordinamento arbitrario?
In altre parole:
Data una query come questa:
SELECT * FROM mytable WHERE <various conditions> ORDER BY <order clause>
è possibile scrivere una query che restituisce solo la prima riga (eventualmente trasformando la clausola di ordine in qualcosa d'altro)?
So che si può fare questo usando LIMIT (MySQL) / ROWNUM (Oracle) o simili, ma non è SQL standard.
Lo so anche che si può fare questo recupero del valore / min max siete interessati a in una sottoquery (utilizzando MIN () / MAX ()), quindi utilizzare tale risultato come criterio nella vostra principale SELECT, vale a dire:
SELECT * FROM mytable WHERE <various conditions> AND myMaxColumn=(
SELECT MAX(myMaxColumn) FROM mytable WHERE <various conditions>
)
Ma che funziona solo se voglio ordinare in base a una singola colonna. Vedo alcun modo per generalizzare questo a più colonne (diverso nesting soluzione sopra, ma ciò significherebbe 2 ^ n seleziona momento dell'ordine da n coluns).
Quindi non v'è un modo migliore in SQL standard di nidificazione più subselect?
Una questione collegata è chiesto in Creare una query SQL per recuperare la maggior parte dei record recenti . Tuttavia, le risposte ci suggeriscono sia utilizzando LIMIT & amici, o per usare una sottoquery con un MAX (), come spiegato in precedenza, entrambi i quali non sono soluzioni a mia domanda.
Soluzione
SQL:2003
definisce concetto di funzioni finestra, uno dei quali:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY col1, col2, col3) AS rn
FROM mytable
) q
WHERE rn = 1
restituirà questo primo record.
Per il momento, è supportato da SQL Server
, Oracle
e dal Jul 01, 2009
, da PostgreSQL 8.4
Si noti, tuttavia, che in ROW_NUMBER()
Oracle
è meno efficiente rispetto al modo nativo per limitare i record (i. E. ROWNUM
).
Si veda questo articolo nel mio blog per il confronto delle prestazioni:
SQL:2008
offre un'altra clausola per fare questo:
SELECT *
FROM mytable
ORDER BY
col1, col2, col3
FETCH FIRST 1 ROW ONLY
, ma come per il momento, questa sintassi esatta è supportato da DB2
solo (AFAIK
).
Altri suggerimenti
Se ti ho capito bene, penso che tu stai cercando la clausola OVER, che consente di partizionare i set di risultati, definito come parte della ANSI SQL 2003 Standard .
Non è molto coerente implementata su piattaforme RDBMS.