SQL query to pull locations based on distance from lat/lng, in LINQ2SQL?

帅比萌擦擦* 提交于 2019-12-11 23:39:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!