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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top