En SQL, pour autant que je sache, l'ordre de traitement des requêtes logiques, qui est l'ordre d'interprétation conceptuelle, commence par FROM de la manière suivante:
- DE
- OÙ
- PAR GROUPE
- AYANT
- SÉLECTIONNER
- COMMANDÉ PAR
Après cette liste, il est facile de comprendre pourquoi vous ne pouvez pas avoir d'alias SELECT dans une clause WHERE, car l'alias n'a pas encore été créé. T-SQL (SQL Server) suit strictement cela et vous ne pouvez pas utiliser les alias SELECT jusqu'à ce que vous ayez passé SELECT.
Mais dans MySQL, il est possible d'utiliser des alias SELECT dans la clause HAVING même s'il doit (logiquement) être traité avant la clause SELECT. Comment cela est-il possible?
Pour donner un exemple:
SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate)
HAVING Amount>1;
L'instruction n'est pas valide dans T-SQL (car HAVING fait référence à l'alias SELECT Amount
) ...
Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.
... mais fonctionne très bien dans MySQL.
Sur cette base, je me demande:
- MySQL prend-il un raccourci dans les règles SQL pour aider l'utilisateur? Peut-être en utilisant une sorte de pré-analyse?
- Ou est-ce que MySQL utilise un ordre d'interprétation conceptuelle différent de celui que je pensais que tous les SGBDR suivaient?
la source
SELECT C, ROW_NUMBER() OVER (ORDER BY X) AS RN FROM T GROUP BY C HAVING RN = 1
sera problématique car lesROW_NUMBER
runs après leHAVING
SELECT @rownum:=@rownum + 1 as row ...
. Peut-être que la raison pour laquelle ils prennent en charge les alias SELECT est simplement parce qu'ils le peuvent, car ils ne prennent pas en charge les éléments qui rendraient cela impossible ... qui sait? :)HAVING
et laSELECT
clause peuvent être échangés. Ainsi, il n'y a aucune ambiguïté en faisant cela et peut simplifier l'apparence du code lorsqu'il y a des expressions monstrueuses dansSELECT
.distincts
) ... avecAlias in the Having
malgré la mêmeExplain
sortie. Il se produit donc des variations avec l'Optimizer.Réponses:
Eh bien, lorsque vous avez une question de ce genre, la meilleure source d'informations à mon humble avis est la documentation MySQL. Maintenant au point. C'est le comportement de l'extension MySql
GROUP BY
qui est activé par défaut.Si vous voulez un comportement standard, vous pouvez désactiver cette extension avec
sql_mode
ONLY_FULL_GROUP_BY
Si vous essayez d'exécuter la requête mentionnée ci-dessus dans
ONLY_FULL_GROUP_BY
sql_mode, vous obtiendrez le message d'erreur suivant:Voici la démo SQLFiddle
C'est donc à vous de configurer et d'utiliser votre instance de MySQL.
la source
ORDER BY
, par exemple, peut en fait être gérée bien plus tôt qu'il ne l'est théoriquement, si l'optimiseur constate que les lignes peuvent être initialement lues dans l'ordre à partir d'un index qui est déjà dans l'ordre souhaité.Bonne question.
Je pense que vous devriez exécuter ces requêtes
et vérifiez comment la requête est réécrite. je suis sûr que l'optimiseur de requête remplace le montant par COUNT (*)
Comme avec
après optimiseur de requête son quelque chose comme ça.
la source