Domanda

Se ho alcune dichiarazioni UNION come esempio inventato:

SELECT * FROM xxx WHERE z = 1
UNION 
SELECT * FROM xxx WHERE z = 2
UNION
SELECT * FROM xxx WHERE z = 3

Qual è l'ordine predefinito per comportamento ?

I dati di test che sto vedendo essenzialmente non restituiscono i dati nell'ordine sopra specificato. Cioè i dati sono ordinati, ma volevo sapere quali sono le regole di precedenza su questo.

Un'altra cosa è che in questo caso xxx è una vista. La vista unisce 3 diverse tabelle per restituire i risultati desiderati.

È stato utile?

Soluzione

Non esiste un ordine predefinito.

Senza una clausola Ordina per l'ordine restituito non è definito. Ciò significa che SQL Server può riportarli nell'ordine che preferisce.

EDIT: In base a ciò che ho visto, senza un Ordine per, l'ordine in cui i risultati ritornano dipende dal piano di query. Quindi, se esiste un indice che sta utilizzando, il risultato potrebbe tornare in quell'ordine ma, di nuovo, non esiste alcuna garanzia.

Altri suggerimenti

Per quanto riguarda l'aggiunta di una clausola ORDER BY:

Questo è probabilmente elementare per la maggior parte qui, ma ho pensato di aggiungere questo. A volte non vuoi mescolare i risultati, quindi vuoi i risultati della prima query, poi la seconda e così via. Per fare ciò aggiungo solo una prima colonna fittizia e ordina per quella. A causa di possibili problemi con l'oblio di una colonna nei sindacati, di solito uso ordinali nella clausola order by, non nomi di colonne.

Ad esempio:

SELECT 1, * FROM xxx WHERE z = 'abc'
UNION ALL
SELECT 2, * FROM xxx WHERE z = 'def'
UNION ALL
SELECT 3, * FROM xxx WHERE z = 'ghi'
ORDER BY 1

La colonna ordinaria fittizia è utile anche nei momenti in cui eseguirò due query e so che solo una restituirà risultati. Quindi posso solo controllare l'ordinale dei risultati restituiti. Questo mi evita di dover effettuare più chiamate al database e il controllo del set di risultati più vuoto.

Ho appena trovato la risposta effettiva.

Poiché UNION rimuove i duplicati, fa un DISTINCT SORT. Questo viene fatto prima che tutte le dichiarazioni UNION vengano concatenate (controlla il piano di esecuzione).

Per interrompere un ordinamento, eseguire UNION ALL e anche questo non rimuoverà i duplicati.

Se ti interessa l'ordine in cui vengono restituiti i record, DEVI utilizzare un ordine entro.

Se lo lasci fuori, potrebbe apparire organizzato (in base agli indici scelti dal piano di query), ma i risultati che vedi oggi potrebbero NON essere i risultati che ti aspetti e potrebbe persino cambia quando viene eseguita la stessa query domani.

Modifica: alcuni esempi validi e specifici: (tutti gli esempi sono server MS SQL)

  • Il blog di Dave Pinal descrive come due query molto simili possono mostrare un ordine apparente diverso, poiché vengono utilizzati indici diversi:

    SELECT ContactID FROM Person.Contact
    SELECT *         FROM Person.Contact
    
  • Conor Cunningham mostra come l'ordine apparente può cambiare quando la tabella diventa più grande (se l'ottimizzatore delle query decide di utilizzare un piano di esecuzione parallelo).

  • Hugo Kornelis dimostra che l'ordine apparente è non sempre basato sulla chiave primaria. Ecco il suo post di follow-up con spiegazione.

Un UNION può essere ingannevole rispetto all'ordinamento del set di risultati perché un database a volte utilizzerà un metodo di ordinamento per fornire il DISTINCT implicito in UNION, il che fa sembrare che le righe siano deliberatamente ordinate - questo non si applica a UNION ALL per il quale non esiste un implicito distinto, ovviamente.

Tuttavia, esistono algoritmi per il distinto implicito, come il metodo hash di Oracle in 10g +, per il quale non verrà applicato alcun ordine.

Come dice DJ, usa sempre un ORDER BY

È molto comune imbattersi in codice scritto male che presuppone che i dati della tabella vengano restituiti nell'ordine di inserimento e il 95% delle volte che il programmatore se ne va con esso e non è mai consapevole che questo è un problema come in molti database comuni (MSSQL , Oracle, MySQL). È ovviamente un errore completo e dovrebbe sempre essere corretto quando viene riscontrato e sempre, senza eccezioni, utilizzare una clausola Order By.

Dalla mia esperienza pratica puoi cambiare l'ordine usando " UNION " contro " UNION ALL " ... vale a dire se la tua query è come

Select Count(*) from Table A
UNION 
Select Count(*) from Table B

result is
10
26

puoi invertire l'ordine sostituendo " UNION " con " UNION ALL " ... quindi il risultato sarà

26
10
scroll top