No SQL, até onde eu sei, a ordem de processamento da consulta lógica, que é a ordem de interpretação conceitual, começa com FROM da seguinte maneira:
- A PARTIR DE
- ONDE
- GRUPO POR
- TENDO
- SELECT
- ORDENAR POR
Após esta lista, é fácil ver por que você não pode ter aliases SELECT em uma cláusula WHERE, porque o alias ainda não foi criado. O T-SQL (SQL Server) segue isso estritamente e você não pode usar aliases SELECT até que você tenha passado por SELECT.
Mas no MySQL é possível usar aliases SELECT na cláusula HAVING, mesmo que deva (logicamente) ser processada antes da cláusula SELECT. Como isso pode ser possível?
Para dar um exemplo:
SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate)
HAVING Amount>1;
A instrução é inválida no T-SQL (porque HAVING está se referindo ao alias SELECT Amount
) ...
Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.
... mas funciona muito bem no MySQL.
Com base nisso, estou me perguntando:
- O MySQL está usando um atalho nas regras SQL para ajudar o usuário? Talvez usando algum tipo de pré-análise?
- Ou o MySQL está usando uma ordem de interpretação conceitual diferente daquela que eu todo o RDBMS estava seguindo?
SELECT C, ROW_NUMBER() OVER (ORDER BY X) AS RN FROM T GROUP BY C HAVING RN = 1
será problemático como as ROW_NUMBER
corridas após oHAVING
SELECT @rownum:=@rownum + 1 as row ...
. Talvez a razão pela qual eles apóiam os aliases SELECT simplesmente seja porque eles podem, devido ao fato de não apoiarem coisas que tornariam isso impossível ... quem sabe? :)
HAVING
e a SELECT
cláusula podem ser trocadas. Portanto, não há ambiguidade em fazer isso e pode simplificar a aparência do código quando houver expressões monstruosas SELECT
.