Using column alias in WHERE clause of MySQL query produces an error
You can only use column aliases in GROUP BY, ORDER BY, or HAVING clauses.
Standard SQL doesn't allow you to
refer to a column alias in a WHERE
clause. This restriction is imposed
because when the WHERE code is
executed, the column value may not yet
be determined.
Copied from MySQL documentation
As pointed in the comments, using HAVING instead may do the work. Make sure to give a read at this question too: WHERE vs HAVING.
Can you use an alias in the WHERE clause in mysql?
You could use a HAVING clause, which can see the aliases, e.g.
HAVING avg_rating>5
but in a where clause you'll need to repeat your expression, e.g.
WHERE (sum(reviews.rev_rating)/count(reviews.rev_id))>5
BUT! Not all expressions will be allowed - using an aggregating function like SUM will not work, in which case you'll need to use a HAVING clause.
From the MySQL Manual:
It is not allowable to refer to a
column alias in a WHERE clause,
because the column value might not yet
be determined when the WHERE clause
is executed. See Section B.1.5.4,
“Problems with Column Aliases”.
MySQL column ALIAS in WHERE clause
Your query doesn't work, because WHERE statement executes before SELECT statement.
You should use HAVING statement to filtering of calculating fields. For example:
SELECT fullname,
(SELECT MAX(login_time)
FROM login_details
WHERE reg_id=registration) AS login_time
FROM search_result
WHERE hire_work=0
GROUP BY fullname
HAVING login_time < '2018-05-22 18:09:00'
Also, subqueries aren't good practice. You can rewrite this query with JOIN
SELECT search_result.fullname,
MAX(login_details.login_time) AS login_time
FROM search_result
JOIN login_details ON login_details.reg_id=search_result.registration
WHERE search_result.hire_work=0
GROUP BY fullname
HAVING login_time < '2018-05-22 18:09:00'
And.. Instead of a constant date, you can use the following expression: NOW() - INTERVAL 180 DAY
. For example:
SELECT search_result.fullname,
MAX(login_details.login_time) AS login_time
FROM search_result
JOIN login_details ON login_details.reg_id=search_result.registration
WHERE search_result.hire_work=0
GROUP BY fullname
HAVING login_time < NOW() - INTERVAL 180 DAY
MYSQL using alias in the WHERE clause
MySQL extends the use of the HAVING
clause, which can be used for this purpose. If the query is not an aggregation query, then HAVING
still does filtering -- but it allows aliases.
So, you can write:
SELECT n.nid AS nid, l.name AS l, (6371.0 * ACOS(SIN((l.latitude * RADIANS(1))) * SIN((28.755925 * RADIANS(1))) + COS((l.latitude * RADIANS(1))) * COS((28.755925 * RADIANS(1))) * COS((l.longitude * RADIANS(1)) - (-81.346395 * RADIANS(1))))) AS distance
FROM node n LEFT JOIn
location_instance li
ON n.vid = li.vid LEFT JOIN
location l
ON li.lid = l.lid
WHERE n.status = 1 AND n.type IN ('locations')
HAVING distance <= 100
ORDER BY distance
LIMIT 10;
Notes:
- If
status
is a number, which seems likely, then you should compare to a number, not a string. - Table aliases make the query easier to write and to read.
- Although
status
andtype
could go in theHAVING
clause, I suspect that they are better in theWHERE
(I suspect thatHAVING
could affect optimization choices). - You could use a subquery, but that would store all the data in the table.
How can I use alias name in where clause in MySQL?
Wrap a part of your current query up in a derived table:
select * from
(
SELECT
*,
CASE roles.rol_active
WHEN '1' THEN 'yes'
WHEN '0' THEN 'no'
END AS roles_active
FROM
roles
) as dt
WHERE
rol_is_deleted =
AND (rol_name LIKE '%ac%'
OR rol_display_name LIKE '%ac%'
OR rol_description LIKE '%ac%'
OR rol_active LIKE '%ac%'
OR rol_updated_by LIKE '%ac%'
OR rol_updated_at LIKE '%ac%')
ORDER BY rol_name asc
LIMIT 10 OFFSET 0;
You can even have two separate WHERE
clauses. One for column conditions in the sub-query, and another one for column alias conditions in the outer query. I.e. something like:
...
WHERE column-conditions
) as dt
WHERE column-alias-conditions
...
Using alias in the WHERE and HAVING statements?
Only MySQL permits alises in HAVING
, it is not standard SQL (see here: https://dba.stackexchange.com/questions/50391/why-does-mysql-allow-having-to-use-select-aliases ) please note that no other major RDBMS allows the use of aliases in WHERE
or HAVING
.
The reason you can't use aliases in WHERE
(and HAVING
) is because SELECT
is actually evaluated after most other sub-clauses: https://stackoverflow.com/a/21693272/159145
A
SELECT
query is evaluated, conceptually, in the following order:
- The
FROM
clause- The
WHERE
clause- The
GROUP BY
clause- The
HAVING
clause- The
SELECT
clause- The
ORDER BY
clause
So your query:
SELECT
customer_id,
address_id AS addressID
FROM
customer
WHERE
addressID = 5
Is evaluated in this order:
1: FROM
customer
2: WHERE
address_id = 5
3: SELECT
customer_id,
address_id AS addressID
As you cans see, if the WHERE
part referenced addressID
instead of address_id
the query execution engine would complain because addressID
is not defined at that point.
MySQL does permit the referencing of (normal) aliases in HAVING
by doing a (non-standard) neat trick where it partially evaluates the SELECT
before it evaluates HAVING
- and because MySQL has a handling of aliases that means the evaluation engine can be sure that the alias is valid (which is why most other RDBMS engines don't allow the use of aliases in HAVING
when they otherwise should be able to). But you can't use an alias in WHERE
because if there's a GROUP BY
then it might render an alias meaningless, consider:
SELECT
SUM( foo ) AS baz,
created
FROM
foo
WHERE
baz > 5 -- Meaningless: the GROUP BY hasn't been evaluated yet, so `baz` is unavailable
GROUP BY
created
MySQL explains this in their manual: https://dev.mysql.com/doc/refman/5.7/en/problems-with-alias.html
Standard SQL disallows references to column aliases in a
WHERE
clause. This restriction is imposed because when theWHERE
clause is evaluated, the column value may not yet have been determined.The
WHERE
clause determines which rows should be included in theGROUP BY
clause, but it refers to the alias of a column value that is not known until after the rows have been selected, and grouped by theGROUP BY
.
Referencing a column alias in the WHERE clause
I would recommend writing the WHERE
as:
WHERE fila_mailing = 2638 AND
F1STA ='ANSWER' AND
CLASSE1 IN ('VC2', 'VC3') AND
FONE1 LIKE '31%' AND
LASTCALL >= '2020-10-02' AND
LASTCALL < '2020-10-31'
Note the changes to the logic:
FONE1
appears to be a string, so the comparison uses string operations.- The
DATETIME
comparisons uses>=
and<
rather thanBETWEEN
so the last second on the last day is not missed. - The date format is simplified.
How do I use alias in where clause?
The SQL-Server docs says:
column_alias can be used in an ORDER BY clause, but it cannot be used in a WHERE, GROUP BY, or HAVING clause.
Similar in the MySQL doc it says:
Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.
In MySQL you can at least reuse aliases in the SELECT clause
Referring to a Column Alias in a WHERE Clause
SELECT
logcount, logUserID, maxlogtm,
DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE ( DATEDIFF(day, maxlogtm, GETDATE() > 120)
Normally you can't refer to field aliases in the WHERE
clause. (Think of it as the entire SELECT
including aliases, is applied after the WHERE
clause.)
But, as mentioned in other answers, you can force SQL to treat SELECT
to be handled before the WHERE
clause. This is usually done with parenthesis to force logical order of operation or with a Common Table Expression (CTE):
Parenthesis/Subselect:
SELECT
*
FROM
(
SELECT
logcount, logUserID, maxlogtm,
DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
) as innerTable
WHERE daysdiff > 120
Or see Adam's answer for a CTE version of the same.
Related Topics
How to Change MySQL Table Names in Linux Server to Be Case Insensitive
Insert Results of a Stored Procedure into a Temporary Table
Split Function Equivalent in T-Sql
How to Delete Duplicate Rows in SQL Server
How to Declare a Variable in a Postgresql Query
Selecting With Multiple Where Conditions on Same Column
How to Select from Stored Procedure
Group by Clause in MySQL and Postgresql, Why the Error in Postgresql
Simulate Lag Function in MySQL
Commit Data in a MySQL Container
Insert Text With Single Quotes in Postgresql
Managing and Debugging SQL Queries in Ms Access
Querying Spark SQL Dataframe With Complex Types
How to Access the "Previous Row" Value in a Select Statement