2012-06-05 13 views
5

In una query MySQL, quando si utilizza l'opzione DISTINCT, si applica ORDER BY dopo la rimozione dei duplicati? In caso contrario, c'è un modo per farlo farlo? Penso che stia causando alcuni problemi con il mio codice.L'ORDER BY si applica prima o dopo DISTINCT?

EDIT:
Ecco qualche informazione in più su ciò che sta causando il mio problema. Capisco che, a prima vista, questo ordine non sarebbe importante, dal momento che mi occupo di righe duplicate. Tuttavia, questo non è completamente il caso, dal momento che sto usando un INNER JOIN per ordinare le righe.

dire che ho un tavolo di discussioni del forum, che contiene questi dati:

+----+--------+-------------+ 
| id | userid | title | 
+----+--------+-------------+ 
| 1 |  1 | Information | 
| 2 |  1 | FAQ   | 
| 3 |  2 | Support  | 
+----+--------+-------------+ 

Ho anche una serie di messaggi in un'altra tabella come questa:

+----+----------+--------+---------+ 
| id | threadid | userid | content | 
+----+----------+--------+---------+ 
| 1 |  1 |  1 | Lorem | 
| 2 |  1 |  2 | Ipsum | 
| 3 |  2 |  2 | Test | 
| 4 |  3 |  1 | Foo  | 
| 5 |  2 |  3 | Bar  | 
| 6 |  3 |  5 | Bob  | 
| 7 |  1 |  2 | Joe  | 
+----+----------+--------+---------+ 

Sto usando il seguente MySQL query per ottenere tutti i thread, quindi ordinarli in base all'ultimo post (supponendo che i post con ID più elevati siano più recenti:

SELECT t.* 
FROM Threads t 
INNER JOIN Posts p ON t.id = p.threadid 
ORDER BY p.id DESC 

Questo funziona, e genera qualcosa di simile:

+----+--------+-------------+ 
| id | userid | title | 
+----+--------+-------------+ 
| 1 |  1 | Information | 
| 3 |  2 | Support  | 
| 2 |  1 | FAQ   | 
| 3 |  2 | Support  | 
| 2 |  1 | FAQ   | 
| 1 |  1 | Information | 
| 1 |  1 | Information | 
+----+--------+-------------+ 

Tuttavia, come si può vedere, le informazioni sono corrette, ma ci sono le righe duplicate. Mi piacerebbe rimuovere tali duplicati, quindi ho usato invece SELECT DISTINCT. Tuttavia, questo ha prodotto il seguente:

+----+--------+-------------+ 
| id | userid | title | 
+----+--------+-------------+ 
| 3 |  2 | Support  | 
| 2 |  1 | FAQ   | 
| 1 |  1 | Information | 
+----+--------+-------------+ 

Questo è ovviamente sbagliato, dal momento che la discussione "Informazioni" dovrebbe essere in cima. Sembrerebbe che utilizzando DISTINCT i duplicati vengano rimossi dall'alto verso il basso, quindi rimangono solo le righe finali. Ciò causa alcuni problemi nell'ordinamento.

In questo caso, o sto analizzando le cose in modo errato?

+2

Quale problema pensi che stia causando? Che differenza avrebbe fatto? – eggyal

+1

perché dovrebbe importare? prima o dopo l'applicazione distinta, l'ordine dovrebbe essere lo stesso – Rodolfo

+1

puoi mostrarci una query di esempio su cosa stai provando e il problema reale che stai incontrando? –

risposta

5

Due cose da capire:

  1. In generale, gruppi di risultati sono unordered a meno che non si specifica una clausola ORDER BY; nella misura in cui si specifica un valore non-strict order (ad esempio, ORDER BY su colonne non univoche), l'ordine in cui i record che sono uguali sotto quell'ordine compaiono all'interno del set di risultati non è definito.

    Sospetto che stiate specificando un ordine non rigoroso, che è la radice dei vostri problemi: assicuratevi che il vostro ordine sia rigoroso specificando ORDER BY su un insieme di colonne che è sufficiente per identificare in modo univoco ogni record per il quale preoccuparsi della sua posizione finale nel set di risultati.

  2. DISTINCT may use GROUP BY, che fa ordinare i risultati dalle colonne raggruppate; ovvero, SELECT DISTINCT a, b, c FROM t produrrà un set di risultati che appare come se fosse stato applicato ORDER BY a, b, c. Ancora una volta, specificare un ordine sufficientemente rigoroso per soddisfare le tue esigenze annullerà questo effetto.


Dopo l'aggiornamento, tenendo presente il punto # 2 di cui sopra, è evidente che l'effetto di raggruppare i risultati per ottenere DISTINCT rende impossibile poi ordine dalla colonna non raggruppata p.id; invece, vuoi:

SELECT t.* 
FROM  Threads t INNER JOIN Posts p ON t.id = p.threadid 
GROUP BY t.id 
ORDER BY MAX(p.id) DESC 
+0

Fantastico, grazie, funziona. Quindi, per confermare, 'MAX()' confronta usando il valore massimo di 'p.id' in ciascun gruppo? –

+0

@JakeKing: è corretto. – eggyal

+0

Cool, grazie ancora. –

1

DISTINCT informa MySQL come creare un set di righe per voi, ORDER BY fornisce un suggerimento su come deve essere presentato questo set di righe. Quindi la risposta è: DISTINCT prima, ORDER BY ultimo.

+3

Ma, in realtà, 'DISTINCT' è implementato ordinando i risultati ... quindi forse no se l'ottimizzatore usa lo stesso ordine per entrambe le attività. – eggyal

+0

In questo caso, come indicato da eggyval, esiste un'eccezione (http://forge.mysql.com/w/images/a/ae/HowMySQLHandlesOrderGroupDistinct.pdf). Quando DISTINCT è raggruppato con ORDER BY, esegue prima l'ordinamento (filesort). –

1

L'ordine di applicazione di e ORDER BY, nella maggior parte dei casi, non influisce sull'output finale.

Tuttavia, se si utilizza anche GROUP BY, questo avrà effetto sull'output finale. In questo caso, lo ORDER BY viene eseguito dopo il GROUP BY, che restituisce risultati imprevisti (supponendo che si aspetti che l'ordinamento venga eseguito prima del raggruppamento).

+0

['DISTINCT' può utilizzare' GROUP BY'] (http://dev.mysql.com/doc/en/distinct-optimization.html). Cosa farebbe l'ordinamento * prima che il gruppo * compia quello che in seguito lo esegue (tenendo presente che la selezione di colonne non raggruppate senza una funzione di aggregazione produce risultati indeterminati - non rilevante in questo caso comunque come 'DISTINCT' non garantisce che tali colonne esistano)? – eggyal

+0

@eggyal, il problema non è con 'DISTINCT', ma con' GROUP BY' e 'ORDER BY'. Se le righe sono raggruppate, ma non selezionate, 'DISTINCT' non aiuta nulla e la query potrebbe restituire i valori di riga" errati "(ad esempio un 'id', che verrà utilizzato in seguito per recuperare i valori). – 0b10011

Problemi correlati