Reputation: 145
I have the following MySQL query
SELECT
(m.speed * TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
(m.origin_x + distance_traveled) AS new_x,
(m.origin_y + distance_traveled) AS new_y,
m.city_id
FROM missions AS m
WHERE
(new_x >= 1 AND new_x <= 15)
AND
(new_y >= 1 AND new_y <= 15)
Is there any way to use distance_traveled
as a sort of variable just for this query? I wouldn't want to calculate the same math every time it is needed in the same query.
This query currently outputs the error
Unknown column 'distance_traveled' in 'field list'
Thanks!
Upvotes: 0
Views: 45
Reputation: 15951
You can get away with this session variable trick, but opinions on how reliable they are varies widely:
Edit: As another answer made me notice, the result fields are being used in the WHERE, it might be safe in a HAVING, but even then I would no longer suggest it just to make your query shorter.
Edit#2: Since there were so many comments, I hesitate to delete the answer; instead I will add inline comments to show what is wrong.
SELECT
@someVar := (m.speed * TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
(m.origin_x + @someVar) AS new_x,
(m.origin_y + @someVar) AS new_y,
m.city_id
FROM missions AS m
WHERE
(new_x >= 1 AND new_x <= 15) // Referencing aliases from the SELECT
AND // is not allowed; those values are not
(new_y >= 1 AND new_y <= 15) // actually determined until after the
// WHERE is evaluated. Even if that
// were not the case, crossing clauses
// with session variables (which this
// effectively does) is a recipe for
// disaster.
;
Upvotes: 0
Reputation: 1269973
Unfortunately, MySQL does not offer a solution for the from
clause that is convenient, reliable, and efficient. A subquery ends up getting materialized. Variables are unreliable.
It does, however, extend the having
clause for this case. So, you can replace the where
with having
and do:
SELECT (m.speed * TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
(m.origin_x + (m.speed * TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) )
) AS new_x,
(m.origin_y + (m.speed * TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) )
) AS new_y,
m.city_id
FROM missions m
HAVING (new_x >= 1 AND new_x <= 15) AND
(new_y >= 1 AND new_y <= 15)
Upvotes: 1
Reputation: 21532
Mysql still does not implement constant table expressions, therefore we need to go old school for this one:
SELECT
m.distance_traveled,
m.new_x,
m.new_y,
m.city_id
FROM (
SELECT
`missions`.*,
(speed * TIMESTAMPDIFF(MINUTE, arrival, departure)) AS distance_traveled,
(speed * TIMESTAMPDIFF(MINUTE, arrival, departure)) + origin_x AS new_x,
(speed * TIMESTAMPDIFF(MINUTE, arrival, departure)) + origin_y AS new_y
FROM `missions`
) m
WHERE
m.new_x >= 1 AND m.new_x <= 15
AND
m.new_y >= 1 AND m.new_y <= 15
Upvotes: 1