Oracle
 sql >> Database >  >> RDS >> Oracle

Funzione Oracle Analytic per il valore minimo nel raggruppamento

Penso che la funzione Rank() non sia la strada da percorrere, per due motivi.

In primo luogo, è probabilmente meno efficiente di un metodo basato su Min().

La ragione di ciò è che la query deve mantenere un elenco ordinato di tutti gli stipendi per reparto durante la scansione dei dati e il grado verrà quindi assegnato in seguito rileggendo questo elenco. Ovviamente in assenza di indici che possono essere sfruttati per questo, non è possibile assegnare un rango fino a quando non è stato letto l'ultimo dato e la manutenzione dell'elenco è onerosa.

Quindi le prestazioni della funzione Rank() dipendono dal numero totale di elementi da scansionare e, se il numero è sufficiente per trasferire l'ordinamento su disco, le prestazioni crolleranno.

Questo è probabilmente più efficiente:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

Questo metodo richiede solo che la query mantenga un valore singolo per reparto rispetto al valore minimo riscontrato finora. Se si incontra un nuovo minimo allora il valore esistente viene modificato, altrimenti il ​​nuovo valore viene scartato. Il numero totale di elementi che devono essere mantenuti in memoria è correlato al numero di reparti, non al numero di righe scansionate.

Potrebbe essere che Oracle abbia un percorso di codice per riconoscere che il Rank non ha davvero bisogno di essere calcolato in questo caso, ma non ci scommetterei.

Il secondo motivo per cui non mi piace Rank() è che risponde semplicemente alla domanda sbagliata. La domanda non è "Quali record hanno lo stipendio che è il primo posto in classifica quando gli stipendi per dipartimento sono in ordine crescente", ma "Quali record hanno lo stipendio che è il minimo per dipartimento". Questo fa una grande differenza per me, almeno.