Reputation: 159
Let's say I have a series of locations and their X, Y coordinates:
L1(X1, Y1) L2(X2, Y2) L3(X3, Y3) ... L10000(X10000, Y10000)
And I have a function that returns the distance between 2 locations: distance(L1, L2) = 5 miles
For a given location, how do I find all of the locations within 100 miles? Or if it's easier, the 50 closest locations
Our setup is a SQL Server table of locations and their zip codes. The function takes 2 zip codes, looks up the latitude / longitude of each and returns the distance. We can cache the results since they don't change very often.
Upvotes: 2
Views: 2467
Reputation: 1831
Use a Kd-tree if you can store all location in memory (lat/lon/id). See my answer to another question Kd-trees allows for efficient nearest neighbor search and k-nearest neighbor search. Average time complexity is O(log n). If you can't store all locations in memory, check if your database supports spatial indices.
Upvotes: 1
Reputation: 1282
One solution is to write a function like the following that is generic and will allow for cutstomization:
Location[] findLocationsWithinDist(Location L1, Integer dist, LocationsList locations){
LocationList results;
foreach(location : locations){
if(dist(L1, location) <= dist)
results.add(location);
}
return results;
}
You could have a data structure that stores each location with a list of locations within a certain range. Then, you would need to update this data structure everytime you added a new location. That seems like a separate problem though.
Upvotes: 0
Reputation: 532445
You don't really give us a lot of information about the table structure so it's hard to give you an exact answer. However, let's say the target zip code is supplied to the query as parameter, P1. Further let's say table T has id, name, and zip fields. To find all locations within 100 miles we can use
select id, name, zip, distance(zip,P1) as distance
from T
where distance(zip,P1) <= 100
For a top 50 query
select top 50 id, name, zip, distance(zip,P1) as distance
from T
order by distance(zip,P1)
A better solution would be to calculate the latitude and longitude of each location and store it in the database. You can think skip the latitude/longitude look up in your function and improve the speed dramatically. I assume that you've already got the code to calculate the great circle distance in your existing function.
Upvotes: 0
Reputation: 1326
You would have to loop through them and simply throw out all the locations that are further away that 100miles and it will be O(N)
SELECT Location FROM Table WHERE (POWER(Location.X-Selected.X,2) + POWER(Location.Y-Selected.Y,2)) < POWER(Distance,2)
Location would be the location entry. Selected would be your selected city just replace it's X and Y with the respective location.
My SQL is a bit rusty so shout if there's a mistake and I'll fix it.
Upvotes: 0