Reputation: 287
In my database I calculate distance between nodes with:
SELECT DISTINCT
dest.name,
AsText(orig.location),
AsText(dest.location),
round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) as distance
FROM nodes orig,
nodes dest
WHERE orig.name='GERP'
I would like to add
and distance < dest.visibility
at the end, but am told that distance is an unknown column.
Any insight very much appreciated.
Upvotes: 0
Views: 274
Reputation: 129403
You can not use the result set calculated column name in the where clause.
You need to (sadly) re-use the whole expression you used to calculate it
and round((glength(linestringfromwkb(linestring((orig.location), (dest.location))))))
< dest.visibility
There are two work-arounds:
If you create the text of the query outside of SQL (e.g. from Perl, PHP etc...), you can store the expression in a string before the query and re-use the string:
$long_expr = "round((glength(linestringfromwkb(linestring((orig.location), (dest.location))))))";
$sql = qq[SELECT DISTINCT
dest.name, AsText(orig.location), AsText(dest.location), $long_expr as distance ... and $long_expr < dest.visibility
Store the original query (sans the last AND) in a temp table (but inlcude visibility
column in the select), and then do the following
SELECT * from #temp_table
WHERE distance < visibility
Same as #2, but instead of temp table, do a subquery.
Upvotes: 0
Reputation: 32575
Use a subquery, then you only have to type the formula in once (and if you need to change it, you only need to change it once).
SELECT
dest.name,
dest.visibility,
AsText(orig.location),
AsText(dest.location),
distance
FROM (
SELECT DISTINCT
dest.name,
dest.visibility,
AsText(orig.location),
AsText(dest.location),
round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) as distance
FROM nodes orig,
nodes dest
WHERE orig.name='GERP'
) AS nodeDistances
WHERE nodeDistainces.distance < visibility
Upvotes: 2
Reputation: 11760
HAVING is your friend.
A select_expr can be given an alias using AS alias_name. The alias is used as the expression's column name and can be used in GROUP BY, ORDER BY, or HAVING clauses.
To accommodate both standard SQL and the MySQL-specific behavior of being able to refer columns in the SELECT list, MySQL 5.0.2 and up permit HAVING to refer to columns in the SELECT list, columns in the GROUP BY clause, columns in outer subqueries, and to aggregate functions.
Note that HAVING can't be optimized and will be dog slow. Not a new problem with your query, though...
Upvotes: 1
Reputation: 332581
Use:
SELECT DISTINCT
dest.name,
AsText(orig.location),
AsText(dest.location),
round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) as distance
FROM nodes orig,
nodes dest
WHERE orig.name = 'GERP'
AND round((glength(linestringfromwkb(linestring((orig.location), (dest.location)))))) < dest.visibility
SQL doesn't allow accessing column aliases in the WHERE clause -- the earliest MySQL supports is the GROUP BY
clause.
Also, your query lacks criteria to join the two table instances -- resulting in a cartesian product.
Upvotes: 0
Reputation: 120937
No, but you can add
and dest.visibility > round((glength(linestringfromwkb(linestring((orig.location), (dest.location))))))
mysql should be smart enough to only compute the expression once.
Upvotes: 1