Pourquoi MySQL permettent de “group by” les requêtes SANS les fonctions d'agrégation?
Surprise -- c'est parfaitement valide requête MySQL:
select X, Y from someTable group by X
Si vous avez essayé cette requête dans la base de données Oracle ou SQL Server, vous devez obtenir l'naturelles message d'erreur:
Column 'Y' is invalid in the select list because it is not contained in
either an aggregate function or the GROUP BY clause.
Alors, comment MySQL déterminer qui Y à afficher pour chaque X? Il choisit juste un. À partir de ce que je peux dire, il choisit juste le premier il Y trouve. Le raisonnement étant, si Y n'est ni une fonction d'agrégation, ni dans la clause group by, puis en spécifiant “sélectionnez-Y” dans votre requête n'a pas de sens pour commencer. Donc, j'ai comme le moteur de base de données sera de retour ce que je veux, et vous l'aimerez.
Il y a même une configuration de MySQL paramètre pour désactiver ce “relâchement”.
http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by
Cet article mentionne même comment MySQL a été critiqué pour être ANSI-SQL non conformes à cet égard.
http://www.oreillynet.com/databases/blog/2007/05/debunking_group_by_myths.html
Ma question est: Pourquoi a été MySQL conçu de cette façon? Ce qui était leur raison d'être pour rompre avec la norme ANSI-SQL?
- Permettez-moi de cette façon. Je vois ce choix de conception comme étant équivalent à un langage de programmation le choix de permettre et d'ignorer, de dire, de laisser "null" être à gauche de la valeur. par exemple, la valeur "null = 3". Il n'y a aucune raison de laisser cela se produire. C'est le genre d'erreur qui est toujours et dangereusement erronée.
- non-sens, qui peut avoir été le cas avant 5.x
- Pouvez-vous donner une référence à votre affirmation?
- Oh, l'homme, j'ai voulu quelque chose ressemblant à ceci, tant dans SQL Server. J'ai toujours imaginé comme "je veux que la "PICKANY(col)," la fonction d'agrégation, ou mieux encore le "UNIQUEVALUE(col) de la fonction", ce qui serait d'erreur si il s'avère ne PAS être constante dans l'ensemble du groupe. J'ai tendance à utiliser "MAX(col)" comme mon "toutes les valeurs sont les mêmes, me donner la valeur" fonction d'agrégation
- Désolé, le commentaire ci-dessus a été un rambly façon de dire "de l'OMI, la réponse serait, car cette fonctionnalité est très utile. Mais je n'ai pas de citation, autres que les "parce que je le veux'".
Vous devez vous connecter pour publier un commentaire.
Je crois que c'est pour gérer le cas où le regroupement d'un champ qui impliquerait d'autres domaines sont également regroupés:
Dans ce cas l'utilisateur.le nom sera toujours unique pour chaque utilisateur.id, donc il y a de la commodité de ne pas exiger de l'utilisateur.nom dans le
GROUP BY
de l'alinéa (bien que, comme vous le dites, il est certain champ d'application à des problèmes)MAX(user.name) AS name
dans les requêtes semblables sur la norme ANSI SQL implémentations.SELECT user.id, ANY(user.name) .. GROUP BY user.id
n'est pas indeterministic si il y a un PK de l'utilisateur.id. Évidemment, les seaux de l'utilisateur.nom du sont ramassés à partir de la va contenir qu'une seule valeur unique -- le nom de l'utilisateur dont l'id est groupé. À l'aide deMAX(user.name) AS name
ou de tout autre aggragate est difficile, au mieux (même si l'intention est plus clairement documentée). Pourrait être un cas de "Ça dépend" de nouveau..Selon cette page (5,0 manuel en ligne), c'est pour de meilleures performances et le confort de l'utilisateur.
ORDER BY ... LIMIT 1
... vous avez juste à être prudent quant à savoir que les données que vous recevez dans le non-agrégées colonnes sera aléatoire de toutes les lignes qui correspondent à vos conditions.Malheureusement presque tous les SQL variétés dans des situations où ils cassent ANSI et avoir des résultats imprévisibles.
Il me semble qu'ils l'ont prévu d'être traité comme le "PREMIER(Y)" fonction que de nombreux autres systèmes ont.
Plus que probable, cette construction est quelque chose que MySQL équipe de regret, mais vous ne voulez pas arrêter de soutenir en raison du nombre de demandes qui seraient en rupture.
Rob
MySQL traite c'est une seule colonne DISTINCTE lorsque vous utilisez le GROUPE de sans une fonction d'agrégation. L'utilisation d'autres options, soit vous avez la totalité du résultat de l'autre, ou d'avoir à utiliser des sous-requêtes, etc. La question est de savoir si les résultats sont vraiment prévisibles.
Aussi, de bonnes info est ce fil.
De ce que j'ai lu dans la référence de mysql page, il est dit:
"Vous pouvez utiliser cette fonction pour obtenir de meilleures performances en évitant les colonnes de tri et de regroupement. Cependant, c'est surtout utile lorsque toutes les valeurs de chaque nonaggregated colonne nom ne figure pas dans le GROUPE sont les mêmes pour chaque groupe."
Je vous suggère de lire cette page (lien vers le manuel de référence de mysql):
http://dev.mysql.com/doc/refman/5.5/en//group-by-extensions.html
Sa en fait un outil très utile que tous les autres champs n'ont pas à être dans une fonction d'agrégation lorsque vous groupe par un champ. Vous pouvez manipuler le résultat qui sera retourné par le simple fait de commander d'abord, puis le groupement des après. par exemple, si je voulais obtenir des informations de connexion utilisateur et je voulais voir la dernière fois l'utilisateur connecté, je voudrais faire cela.
Tables
USER_LOGIN_HISTORY a plusieurs lignes pour un seul utilisateur, donc si j'ai rejoint des utilisateurs, il serait de retour, le nombre de lignes. comme je ne m'intéresse qu'à la dernière entrée, je voudrais faire cette
Ce serait de retour une ligne avec le nom de l'utilisateur et la dernière fois que l'utilisateur connecté.