gotchasqlModerate
Why does MySQL allow HAVING to use SELECT aliases?
Viewed 0 times
whyhavingaliasesallowmysqldoesselectuse
Problem
In SQL, as far as I know, the logical query processing order, which is the conceptual interpretation order, starts with FROM in the following way:
Following this list it's easy to see why you can't have SELECT aliases in a WHERE clause, because the alias hasn't been created yet. T-SQL (SQL Server) follows this strictly and you can't use SELECT aliases until you've passed SELECT.
But in MySQL it's possible to use SELECT aliases in the HAVING clause even though it should (logically) be processed before the SELECT clause. How can this be possible?
To give an example:
The statement is invalid in T-SQL (because HAVING is referring to the SELECT alias
...but works just fine in MySQL.
Based upon this, I'm wondering:
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
Following this list it's easy to see why you can't have SELECT aliases in a WHERE clause, because the alias hasn't been created yet. T-SQL (SQL Server) follows this strictly and you can't use SELECT aliases until you've passed SELECT.
But in MySQL it's possible to use SELECT aliases in the HAVING clause even though it should (logically) be processed before the SELECT clause. How can this be possible?
To give an example:
SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate)
HAVING Amount>1;The statement is invalid in T-SQL (because HAVING is referring to the SELECT alias
Amount)...Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'....but works just fine in MySQL.
Based upon this, I'm wondering:
- Is MySQL taking a shortcut in the SQL rules to help the user? Maybe using some kind of pre-analysis?
- Or is MySQL using a different conceptual interpretation order than the one I though all RDBMS were following?
Solution
Well when you have a question of this sort the best source of information IMHO is MySQL documentation. Now to the point. This is the behavior of MySql extension to
MySQL Extensions to GROUP
BY
MySQL extends this behavior to permit the use of an alias in the
HAVING clause for the aggregated column
If you want standard behavior you can disable this extension with
If you try to execute the above-mentioned query in
Non-grouping field 'Amount' is used in HAVING clause: SELECT
YEAR(orderdate), COUNT(*) as Amount FROM Orders GROUP BY
YEAR(orderdate) HAVING Amount > 1
Here is SQLFiddle demo
Therefore it's up to you how to configure and use your instance of MySQL.
GROUP BY which is enabled by default.MySQL Extensions to GROUP
BY
MySQL extends this behavior to permit the use of an alias in the
HAVING clause for the aggregated column
If you want standard behavior you can disable this extension with
sql_mode ONLY_FULL_GROUP_BYSET [SESSION | GLOBAL] sql_mode = ONLY_FULL_GROUP_BY;
If you try to execute the above-mentioned query in
ONLY_FULL_GROUP_BY sql_mode you'll get the following error message:Non-grouping field 'Amount' is used in HAVING clause: SELECT
YEAR(orderdate), COUNT(*) as Amount FROM Orders GROUP BY
YEAR(orderdate) HAVING Amount > 1
Here is SQLFiddle demo
Therefore it's up to you how to configure and use your instance of MySQL.
Context
StackExchange Database Administrators Q#50391, answer score: 13
Revisions (0)
No revisions yet.