2011-08-25 21 views
25

Ho dovuto rivedere un po 'di codice e ho trovato qualcosa che qualcuno ha fatto, e non riesco a pensare a una ragione a mio modo migliore. E probabilmente non lo è, quindi, che è migliore/più sicuro/più efficiente?MAX vs Top 1 - che è meglio?

SELECT MAX(a_date) FROM a_table WHERE a_primary_key = 5 GROUP BY event_id 

O

SELECT TOP 1 a_date FROM a_table WHERE a_primary_key = 5 ORDER BY a_date 

sarei andato con il 2 ° opzione, ma non sono sicuro perché, e se è vero.

risposta

13

Le prestazioni sono generalmente simili, se la tabella è indicizzata.

Worth considerando però: Top solito solo ha un senso se si ordinano i risultati (? Altrimenti, top di ciò)

per l'ordinazione di conseguenza richiede una maggiore elaborazione.

Min non richiede sempre l'ordine. (Dipende solo, ma spesso non hai bisogno di ordinare o raggruppare, ecc.)

Nei tuoi due esempi, mi aspetterei che la velocità/x-plan sia molto simile. Puoi sempre passare alle tue statistiche per essere sicuro, ma dubito che la differenza sarebbe significativa.

+1

SQL Server TOP 1 si comporta diversamente da Oracle utilizzando rowNum = 1. Oracle in realtà acquisisce il primo che trova PRIMA dell'ordinamento, quindi questo metodo è valido solo per SQL Server. Un altro vantaggio di questo TOP 1 rispetto a Max() è che puoi prendere tutte le colonne che vuoi, purché includi l'ordine applicabile. Ho provato a utilizzare Max() e ho trovato persino con GROUP BY che non sembrava produrre solo 1 record. Forse qualcuno come mojo più forte può dire come ottenere solo una riga se vuoi ottenere la parte superiore da più colonne senza una sotto-query? – gordon

10

Sono domande diverse.

La prima restituisce molti record (il più grande a_date per ogni event_id trovato all'interno a_primary_key = 5)

Il secondo restituisce un record (il più piccolo a_date trovano all'interno a_primary_key = 5).

+2

o.O la prima query restituirà comunque un record –

+1

@Shredder A condizione che "a_primary_key" sia in realtà una chiave primaria, lo sarà. Ma se è una chiave primaria, hai solo una data in 'a_date', e non hai bisogno né di' max' né di 'top'. – GSerg

+0

Anche se non lo fosse, restituirà comunque un record. http://www.w3schools.com/sql/sql_func_max.asp –

0

MAX e TOP funzione in modo diverso. La prima query restituirà il valore massimo trovato per a_date che ha uno a_primary_key = 5 per ogni diverso event_id trovato. La seconda query prenderà semplicemente il primo a_date con uno a_primary_key = 5 trovato nel set di risultati.

+1

Non prenderà il primo valore. 'Top', quando combinato con' order by asc', selezionerà il valore più piccolo. – GSerg

+0

wth sei smokin bro, dammi un po 'di quello .. It * will * afferrare il primo valore trovato, e sì, in questo caso sarà il più piccolo dal momento che l'ordine di ASC va dal più piccolo al più grande, rendendo il primo valore il più piccolo .. –

5

Per le query per avere lo stesso risultato che si avrebbe bisogno:

SELECT MAX(a_date) FROM a_table WHERE a_primary_key = 5 

SELECT TOP 1 a_date FROM a_table WHERE a_primary_key = 5 ORDER BY a_date DESC 

Il modo migliore per sapere che è più veloce è quello di verificare il piano di query e fare i vostri punti di riferimento. Ci sono molti fattori che potrebbero influenzare la velocità, come la dimensione della tabella/heap, ecc. E persino diverse versioni dello stesso database possono essere ottimizzate per favorire una query rispetto all'altra.

+3

Non è necessario raggruppare nel primo esempio (perché hai solo un gruppo, secondo la tua clausola WHERE). – Chains

+0

@kuru: non sono sicuro che tu possa utilizzare una funzione aggregata con un gruppo per, ma in tal caso ... hai ragione – vol7ron

+3

Finché stai selezionando solo aggs (come nella tua risposta), sei a posto. Se includi un valore non-agg nella selezione, allora hai bisogno di un gruppo per. – Chains

0

mi esibisco max e superiore su una tabella con 20,00,000+ record, e ha scoperto che Top dare più veloce risultato con ordine da oltre max o la funzione min.

Quindi, il modo migliore è eseguire entrambe le query una alla volta per un po 'di tempo e controllare il tempo trascorso della connessione per.