views:

73

answers:

5

I want to execute a query in which I rename one of the columns using the 'AS' statement and reuse that aliased column name within the 'WHERE' statement. Below is an example:

SELECT lat AS latitude 
FROM poi_table 
WHERE latitude < 500

The problem here is that SQL Server does not like this query because of the WHERE clause and the AS statement name being referenced in the WHERE clause. Can anyone explain why this is happening and what I can do to remedy my situation?

Suppose I were to have a formula that I have aliased in the SELECT portion of the query, how do I tackle that?

SELECT *, 
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) 
AS distance
FROM poi_table 
WHERE distance < 500;
+5  A: 

SQL doesn't typically allow you to reference column aliases in WHERE, GROUP BY or HAVING clauses. SQL Server (and MySQL) do support referencing column aliases in the GROUP BY and HAVING, but I stress that it will cause problems when porting such queries to other databases.

When in doubt, use the actual column name:

SELECT t.lat AS latitude 
  FROM poi_table t
 WHERE t.lat < 500

I added a table alias to make it easier to see what is an actual column vs alias.

Update


A computed column, like the one you see here:

SELECT *, 
       ( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) AS distance
  FROM poi_table 
 WHERE distance < 500;

...doesn't change that you can not reference a column alias in the WHERE clause. For that query to work, you'd have to use:

SELECT *, 
       ( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) AS distance
  FROM poi_table
 WHERE ( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) ) < 500;

Be aware that using a function on a column (IE: RADIANS(lat)) will render an index useless, if one exists on the column.

OMG Ponies
I added another (more slightly complex) example. Would your approach of aliasing the table still work? If not, what would I need to do then?
rohanbk
@rohanbk: Updated answer based on updated updated question example.
OMG Ponies
@OMG Ponies: Thanks
rohanbk
+2  A: 

I am not sure why you cannot use "lat" but, if you must you can rename the columns in a derived table.

select latitude from (SELECT lat AS latitude FROM poi_table) p where latitude < 500
buckbova
+4  A: 

SQL Server is tuned to apply the filters before it applies aliases (because that usually produces faster results). You could do a nested select statement. Example:

SELECT Latitude FROM 
(
    SELECT Lat AS Latitude FROM poi_table
) A
WHERE Latitude < 500

I realize this may not be what you are looking for, because it makes your queries much more wordy. A more succinct approach would be to make a view that wraps your underlying table:

CREATE VIEW vPoi_Table AS 
SELECT Lat AS Latitude FROM poi_table

Then you could say:

SELECT Latitude FROM vPoi_Table WHERE Latitude < 500
tgolisch
Or you could just use [sp_rename](http://msdn.microsoft.com/en-us/library/ms188351.aspx) if you **really** feel the need to rename the column.
OMG Ponies
+1  A: 

This would work on your edited question !

SELECT * FROM (SELECT <Column_List>,  
( 6371*1000 * acos( cos( radians(42.3936868308) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(-72.5277256966) ) + sin( radians(42.3936868308) ) * sin( radians( lat ) ) ) )  
AS distance 
FROM poi_table) TMP
WHERE distance < 500; 
Baaju