Per evitare risultati potenzialmente imprevisti quando si utilizza GROUP BYsenza una funzione di aggregazione, come viene utilizzato nella risposta accettata , poiché MySQL è libero di recuperare QUALSIASI valore all'interno del set di dati da raggruppare quando non si utilizza una funzione di aggregazione [sic] e problemi conONLY_FULL_GROUP_BY . Prendi in considerazione l'utilizzo di un join di esclusione.
Partecipazione di esclusione - Entità non ambigue
Supponendo che il nome e il cognome siano indicizzati in modo univoco (inequivocabile) , un'alternativa a GROUP BYè quella di ordinare utilizzando a LEFT JOINper filtrare il set di risultati, altrimenti noto come JOIN di esclusione.
Vedi dimostrazione
Ordine crescente (AZ)
Per recuperare il nome distinto ordinato per cognome dalla A alla Z.
domanda
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname > t2.lastname
WHERE t2.id IS NULL;
Risultato
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
Ordine decrescente (ZA)
Per recuperare il nome distinto ordinato per cognome da ZA
domanda
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname < t2.lastname
WHERE t2.id IS NULL;
Risultato
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
È quindi possibile ordinare i dati risultanti come desiderato.
Partecipazione di esclusione - Entità ambigue
Se la combinazione di nome e cognome non è univoca (ambigua) e si dispone di più righe con gli stessi valori, è possibile filtrare il set di risultati includendo una condizione OR nei criteri JOIN per filtrare anche per id.
Vedi dimostrazione
dati table_name
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson'),
(4, 'John', 'Doe'),
(5, 'John', 'Johnson')
domanda
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND (t1.lastname > t2.lastname
OR (t1.firstname = t1.firstname AND t1.lastname = t2.lastname AND t1.id > t2.id))
WHERE t2.id IS NULL;
Risultato
| id | firstname | lastname |
|----|-----------|----------|
| 1 | John | Doe |
| 2 | Bugs | Bunny |
Sottoquery ordinata
MODIFICARE
La mia risposta originale utilizzando una subquery ordinata , è stata scritta prima di MySQL 5.7.5 , che non è più applicabile, a causa delle modifiche conONLY_FULL_GROUP_BY . Utilizzare invece gli esempi di join di esclusione sopra riportati.
È anche importante notare; quando ONLY_FULL_GROUP_BYè disabilitato (comportamento originale prima di MySQL 5.7.5) , l'uso di GROUP BYsenza una funzione aggregata può produrre risultati imprevisti, poiché MySQL è libero di scegliere QUALSIASI valore all'interno del set di dati da raggruppare [sic] .
Significa che è possibile recuperare un valore IDo che non è associato alla riga recuperata .lastnamefirstname
AVVERTIMENTO
Con MySQL GROUP BYpotrebbe non produrre i risultati previsti se utilizzato conORDER BY
Vedi esempio di test case
Il miglior metodo di implementazione, per garantire i risultati previsti, è filtrare l'ambito del set di risultati utilizzando una subquery ordinata.
dati table_name
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson')
domanda
SELECT * FROM (
SELECT * FROM table_name ORDER BY ID DESC
) AS t1
GROUP BY FirstName
Risultato
| ID | first | last |
|----|-------|---------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
Confronto
Per dimostrare i risultati imprevisti quando si utilizza GROUP BYin combinazione conORDER BY
domanda
SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC
Risultato
| ID | first | last |
|----|-------|-------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |