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?
mysql
database-internals
Ohlin
fonte
fonte
SELECT C, ROW_NUMBER() OVER (ORDER BY X) AS RN FROM T GROUP BY C HAVING RN = 1
será problemático como asROW_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 aSELECT
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 monstruosasSELECT
.distincts
) ... com aAlias in the Having
apesar da mesmaExplain
saída. Então, alguma variação com o Optimizer está acontecendo.Respostas:
Bem, quando você tem uma pergunta desse tipo, a melhor fonte de informação IMHO é a documentação do MySQL. Agora ao ponto. Esse é o comportamento da extensão MySql ao
GROUP BY
qual está ativado por padrão.Se você deseja um comportamento padrão, pode desativar esta extensão com
sql_mode
ONLY_FULL_GROUP_BY
Se você tentar executar a consulta acima mencionada em
ONLY_FULL_GROUP_BY
sql_mode, receberá a seguinte mensagem de erro:Aqui está a demonstração do SQLFiddle
Portanto, cabe a você como configurar e usar sua instância do MySQL.
fonte
ORDER BY
, por exemplo, pode ser realmente tratado muito mais cedo do que teoricamente, se o otimizador descobrir que as linhas podem ser lidas inicialmente na ordem de um índice que já está na ordem desejada.Boa pergunta.
Eu acho que você deve executar essas consultas
e verifique como a consulta é reescrita. Estamos certos de que o otimizador de consultas substitua Valor por COUNT (*)
Como acontece com
após o otimizador de consultas, é algo assim.
fonte