问题
I want to perform a query (to pull locations within a given distance from a specified lat/lng) against a MS SQL 2008 Server, no geo field types:
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;
This is the haversine formula described here. I'd like to call the query, probably setup as a stored procedure, using LINQ - pulled into an IEnumerable list.
The table essentially looks like this:
Locations Table
- Id - long PK
- Name - nvarchar...
- Lat
- Lng ...
I'm not familiar with the math functions in MS SQL, the query example is MySQL. Will this query port to MS SQL well? Am I asking for problems attempting to do this?
回答1:
The query you've posted should work reasonably well.
However, if you are in the position where you can change your data schema then SQL Server has some native Geography types - and if you could use these then there are built-in functions and built-in indexing which would allow you to execute this type of query much more efficiently - see http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx
回答2:
I'd recommend using the Geolocation class in System.Device.Location instead of writing your own formulas.
If you're running this against a large number of geocoded database entries, a good idea would be to eliminate entries that are definitively not close. If you strip the decimal places from the latitude and longitude, you restrict searches to a 1 degree by 1 degree block (Which is a 69 X 69 mile square). For most national search purposes this limits choices to a manageable initial query without worrying about shaving too many decimal places. The LINQ query that I've devised looks like this:
IQueryable<locations> categoryQuery = from g in context.locations
where ((Int32)userlatitude== (Int32)g.latitude && (Int32)userlongitude == (Int32)g.longitude)
select g;
double distance;
var userCoord = new GeoCoordinate(userlatitude, userlongitude);
foreach (locations locations in
categoryQuery)
{
var endCoord = new GeoCoordinate((double)locations.latitude, (double)locations.longitude);
distance = userCoord.GetDistanceTo(endCoord); //The distance is returned in meters
distance = distance * .000621371192; //So convert it into miles if you're displaying it in the U.S.
Then, do whatever you want to accomplish by sorting upon the location's distance.
回答3:
What problems do you expect?
T-SQL (the SQL derivate of MS SQL Server) supports all of the math functions you used: http://msdn.microsoft.com/en-us/library/ms177516.aspx
来源:https://stackoverflow.com/questions/5549237/sql-query-to-pull-locations-based-on-distance-from-lat-lng-in-linq2sql