在LINQ2SQL中,基于与lat / lng的距离来拉取位置的SQL查询?

时间:2011-04-05 08:36:18

标签: sql linq geolocation

我想针对MS SQL 2008 Server执行查询(从指定的lat / lng拉出给定距离内的位置),没有地理字段类型:

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;

这是haversine formula described here。我想调用查询,可能设置为存储过程,使用LINQ - 拉入IEnumerable列表。

该表基本上如下所示:

地点表

  • Id - 长PK
  • 名称 - nvarchar ......
  • 纬度
  • Lng ......

我不熟悉MS SQL中的数学函数,查询示例是MySQL。这个查询会很好地移植到MS SQL吗?我是否在尝试这样做时遇到问题?

3 个答案:

答案 0 :(得分:2)

您发布的查询应该运行得相当好。

但是,如果您处于可以更改数据模式的位置,那么SQL Server具有一些本机地理类型 - 如果您可以使用这些类型,那么有内置函数和内置索引,这将允许您更有效地执行此类查询 - 请参阅http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx

答案 1 :(得分:1)

我建议在System.Device.Location中使用Geolocation类,而不是编写自己的公式。

如果您针对大量地理编码数据库条目运行此操作,那么一个好主意是消除绝对不接近的条目。如果从纬度和经度中剥离小数位,则将搜索限制为1度1度块(即69 X 69英里的正方形)。对于大多数国家搜索目的,这限制了对可管理的初始查询的选择,而不必担心削减太多小数位。我设计的LINQ查询如下所示:

                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. 

然后,通过对位置的距离进行排序,做任何你想要完成的事情。

答案 2 :(得分:0)

您期待什么问题?
T-SQL(MS SQL Server的SQL派生)支持您使用的所有数学函数:http://msdn.microsoft.com/en-us/library/ms177516.aspx