ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
Je souhaite sélectionner les DISTINCT
résultats dans la FirstName
colonne, mais j'ai besoin des fichiers ID
et LastName
.
Le jeu de résultats doit afficher un seul John
, mais avec un ID
de 1 et un LastName
de Doe.
DISTINCT
n'est pas une fonction. Toutes les réponsesDISTINCT()
sont fausses. L'erreur apparaîtra lorsque vous ne la placerez pas aprèsSELECT
.ALL
les réponses utilisant des parenthèses après le mot distinct sont en effet fausses. Distinct n'est PAS une fonction , il ne peut donc pas accepter de paramètre. Les parenthèses suivantes distinctes sont simplement ignorées. Sauf si vous utilisez PostgreSQL où les parenthèses formeront un "type de données complexe"Réponses:
essayez cette requête
SELECT ID, FirstName, LastName FROM table GROUP BY(FirstName)
la source
5.7.5+
pour laGROUP BY
manipulationLe
DISTINCT
mot-clé ne fonctionne pas vraiment comme vous l'attendez. Lorsque vous utilisezSELECT DISTINCT col1, col2, col3
vous sélectionnez en fait tous les tuples uniques {col1, col2, col3}.la source
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 avecONLY_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 aLEFT 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
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 deGROUP 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
oulastname
peut être extraite qui n'est pas associée à lafirstname
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
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 |
la source
Ordering is done after grouping.
, donc Non pas dans ce cas d'utilisation, en plus MariaDB ignore ORDER BY dans les sous-requêtes (selon le standard SQL) sans aLIMIT
. Vous voudriez utiliser unWindow Function
Pour plus de précisions, vous devriez poser votre question dans le stackexchange DBA , car il s'agit d'une question relative à MySQLGROUP BY
peut sélectionner n'importe quelle valeur dans l'ensemble de données groupées, sauf si une fonction d'agrégation est utilisée sur ces colonnes pour forcer une valeur spécifique. Donclastname
ouid
peut provenir de l'une des lignes ordonnées. L'exemple de sous-requête d'origine était acceptable par défaut dansMySQL <= 5.7.4
mais souffre encore techniquement du problème. Bien que l 'ORDER BY
aide à empêcher une sélection aléatoire, cela reste théoriquement possible, mais avec une probabilité beaucoup moins élevée que sans utiliser laORDER BY
sous - requête.SELECT ID,LastName From TABLE_NAME GROUP BY FirstName HAVING COUNT(*) >=1
la source
HAVING
rendu ma requête 50% plus lente.SELECT firstName, ID, LastName from tableName GROUP BY firstName
la source
Que diriez-vous
`SELECT my_distinct_column, max(col1), max(col2), max(col3) ... FROM my_table GROUP BY my_distinct_column`
la source
Je ne sais pas si vous pouvez le faire avec MySQL, mais vous pouvez utiliser un CTE dans T-SQL
; WITH tmpPeople AS ( SELECT DISTINCT(FirstName), MIN(Id) FROM People ) SELECT tP.Id, tP.FirstName, P.LastName FROM tmpPeople tP JOIN People P ON tP.Id = P.Id
Sinon, vous devrez peut-être utiliser une table temporaire.
la source
Comme l'a souligné fyrye , la réponse acceptée concerne les anciennes versions de MySQL qui
ONLY_FULL_GROUP_BY
n'avaient pas encore été introduites. Avec MySQL 8.0.17 (utilisé dans cet exemple), à moins que vous ne désactiviez,ONLY_FULL_GROUP_BY
vous obtiendrez le message d'erreur suivant:mysql> SELECT id, firstName, lastName FROM table_name GROUP BY firstName;
Une façon de contourner ce problème , non mentionnée par fyrye , mais décrite dans https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html , consiste à appliquer la
ANY_VALUE()
fonction aux colonnes qui sont pas dans laGROUP BY
clause (id
etlastName
dans cet exemple):mysql> SELECT ANY_VALUE(id) as id, firstName, ANY_VALUE(lastName) as lastName FROM table_name GROUP BY firstName; +----+-----------+----------+ | id | firstName | lastName | +----+-----------+----------+ | 1 | John | Doe | | 2 | Bugs | Bunny | +----+-----------+----------+ 2 rows in set (0.01 sec)
Comme indiqué dans les documents susmentionnés,
la source
ANY_VALUE()
car ma réponse et mes commentaires sont axés sur la prévention des ensembles de résultats ambigus et imprévisibles. Comme le nom de la fonction l'indique, cela peut entraîner la récupération de n'importe quelle valeur des lignes sélectionnées. Je suggérerais d'utiliserMAX
ou à laMIN
place.Gardez à l'esprit lorsque vous utilisez le group by et order by that MySQL est la SEULE base de données qui permet d'utiliser des colonnes dans le group by et / ou order by piece qui ne font pas partie de l'instruction select.
Par exemple: sélectionnez colonne1 dans le tableau groupe par colonne2 ordre par colonne3
Cela ne volera pas dans d'autres bases de données comme Postgres, Oracle, MSSQL, etc. Vous devrez faire ce qui suit dans ces bases de données
sélectionnez colonne1, colonne2, colonne3 du tableau grouper par colonne2 ordre par colonne3
Juste quelques informations au cas où vous migreriez votre code actuel vers une autre base de données ou commenceriez à travailler dans une autre base de données et essayez de réutiliser le code.
la source
Vous pouvez utiliser group by pour afficher des valeurs distinctes ainsi que les champs correspondants.
select * from tabel_name group by FirstName
Maintenant, vous avez une sortie comme celle-ci:
Si vous voulez répondre comme
puis utilisez cette requête,
select * from table_name group by FirstName order by ID
la source
SELECT DISTINCT(firstName), ID, LastName from tableName GROUP BY firstName
Serait le meilleur pari IMO
la source
SELECT DISTINCT (column1), column2 FROM table1 GROUP BY column1
la source
DISTINCT()
n'est pas une fonction. DISTINCT et GROUP BY font la même chose, donc aucune raison ne les met tous les deux.