Pour éviter des résultats potentiellement inattendus lors de l'utilisation GROUP BY
sans fonction d'agrégation, comme cela est utilisé dans la réponse acceptée , car MySQL est libre de récupérer N'IMPORTE QUELLE valeur dans l'ensemble de données groupé lorsqu'il n'utilise pas de fonction d'agrégation [sic] et pose des problèmes avec ONLY_FULL_GROUP_BY
. Veuillez envisager d'utiliser une jointure d'exclusion.
Jointure d'exclusion - Entités non ambiguës
En supposant que le prénom et le nom sont indexés de manière unique (sans ambiguïté) , une alternative à GROUP BY
est de trier à l'aide de a LEFT JOIN
pour filtrer le jeu de résultats, autrement connu sous le nom d'exclusion JOIN.
Voir la démonstration
Ordre croissant (AZ)
Pour récupérer le prénom distinct trié par nom de A à Z
Requete
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;
Résultat
| id | firstname | lastname |
|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
Ordre décroissant (ZA)
Pour récupérer le prénom distinct trié par nom de ZA
Requete
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;
Résultat
| id | firstname | lastname |
|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
Vous pouvez ensuite commander les données résultantes comme vous le souhaitez.
Jointure d'exclusion - Entités ambiguës
Si la combinaison du prénom et du nom n'est pas unique (ambiguë) et que vous avez plusieurs lignes des mêmes valeurs, vous pouvez filtrer le jeu de résultats en incluant une condition OR sur les critères JOIN pour filtrer également par id.
Voir la démonstration
données nom_table
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson'),
(4, 'John', 'Doe'),
(5, 'John', 'Johnson')
Requete
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;
Résultat
| id | firstname | lastname |
|
| 1 | John | Doe |
| 2 | Bugs | Bunny |
Sous-requête ordonnée
ÉDITER
Ma réponse originale utilisant une sous - requête ordonnée a été écrite avant MySQL 5.7.5 , qui n'est plus applicable, en raison des changements avec ONLY_FULL_GROUP_BY
. Veuillez plutôt utiliser les exemples de jointure d'exclusion ci-dessus.
Il est également important de noter; lorsque ONLY_FULL_GROUP_BY
est désactivé (comportement d'origine avant MySQL 5.7.5) , l'utilisation de GROUP BY
sans fonction d'agrégation peut donner des résultats inattendus, car MySQL est libre de choisir N'IMPORTE QUELLE valeur dans l'ensemble de données en cours de regroupement [sic] .
Cela signifie qu'une valeur ID
ou lastname
peut être extraite qui n'est pas associée à la firstname
ligne récupérée .
ATTENTION
Avec MySQL GROUP BY
peut ne pas donner les résultats attendus lorsqu'il est utilisé avecORDER BY
Voir l'exemple de cas de test
La meilleure méthode de mise en œuvre, pour garantir les résultats attendus, consiste à filtrer la portée de l'ensemble de résultats à l'aide d'une sous-requête ordonnée.
données nom_table
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson')
Requete
SELECT * FROM (
SELECT * FROM table_name ORDER BY ID DESC
) AS t1
GROUP BY FirstName
Résultat
| ID | first | last |
|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
Comparaison
Pour démontrer les résultats inattendus lors de l'utilisation GROUP BY
en combinaison avecORDER BY
Requete
SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC
Résultat
| ID | first | last |
|
| 2 | Bugs | Bunny |
| 1 | John | Doe |