August 22, 2011 at 9:29 pm
I have an application to calculate the distance between two addresses.
Here is my SQL statement:
"Select store_Name, latitude, longitude,
SQRT(POWER(Latitude - @Latitude, 2) + POWER(Longitude - @Longitude, 2)) as Distance From tbl_Stores Where Distance < 60;"
The error message states that "Invalid column name 'distance'." I think it does not recognize the aliasname. How to get around it?
Also, since not every store has Latitude/Longitude values, some rows may return null value for calculated distance. However, I do need to keep those data rows even I could not run distance comparison. The final data would be something like this:
1. Store1, 34.1, -118.7, 55
2. Store2, 34.2, -118.6, 56
3. Store3, null, null, null
4.
etc.
August 23, 2011 at 12:06 am
You can't use column aliases in WHERE clause. uses the plain expression to compare :
Select store_Name, latitude, longitude,
SQRT(POWER(Latitude - @Latitude, 2) + POWER(Longitude - @Longitude, 2)) as Distance
From tbl_Stores
Where (SQRT(POWER(Latitude - @Latitude, 2) + POWER(Longitude - @Longitude, 2)) < 60)
or (SQRT(POWER(Latitude - @Latitude, 2) + POWER(Longitude - @Longitude, 2)) IS NULL)
August 23, 2011 at 6:44 am
Thanks, Roland. It works perfectly!
August 23, 2011 at 11:02 am
And here is a little "trick" to allow reuse of the calculated column by using CROSS APPLY
Select s.store_Name, s.latitude, s.longitude, d.Distance
From tbl_Stores s
cross apply(select SQRT(POWER(s.Latitude - @Latitude, 2) + POWER(s.Longitude - @Longitude, 2))) as d(Distance)
Where d.Distance < 60
August 23, 2011 at 11:18 am
Hmmm.. interesting to see this... i tried simulating the question by using 3 variations , cte, cross apply ( from nils gustav ) and OP's method.
Here is test code:
select 1 a, crsapp.diffdate
from sys.columns
cross apply ( select DATEDIFF(dd, getdate() , getdate()-10) diffdate ) crsapp
where crsapp.diffdate = 1
; with cte as
( select 1 a,DATEDIFF(dd, getdate() , getdate()-10) diffdate
from sys.columns
)
select * from cte
where diffdate = 1
select 1 a ,DATEDIFF(dd, getdate() , getdate()-10) diffdate
from sys.columns
where DATEDIFF(dd, getdate() , getdate()-10) = 1
To my surprise, all the 3 methods produce identical plans.. hmmm.. time to dig deep :w00t:
August 25, 2011 at 4:20 am
Two issues :
1) If you are using 2008, use the spatial functionality.
2) The sql is non-sargable , every store has to be tested to see if the distance from the point is < 60. Fine if you are 'mom and pop' with 10 stores, not good if you a Walmart with a worldwide operation.
You need to limit the amount of stores tested by adding to the where clause
s.Latitude between @Latitude - 60 and @Latitude + 60 and
s.Longitude between @Longitude - 60 and @Longitude + 60
Math may not be spot on , but you get the idea.
To make full use of potential indexes on longitude and latitude , i would use a self join ie (untested)
select slat.store_Name, slat.latitude, slat.longitude, d.Distance
from tbl_Stores slat
join tbl_Stores slong
on slat.storeId = slong.storeid
cross apply(select SQRT(POWER(slat.Latitude - @Latitude, 2) + POWER(slong.Longitude - @Longitude, 2))) as d(Distance)
Where d.Distance < 60
and slat.latitude between @Latitude -60 and @Latitude +60
and slong.longitude between @longitude -60 and @longitude +60
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply