基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite
Posted
技术标签:
【中文标题】基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite【英文标题】:SQL query to query nearby points of interest based on lat/long - SQLite 【发布时间】:2010-07-02 20:24:07 【问题描述】:给定一个包含三个字段的数据库:
纬度 经度 接近度
Lat 和 Long 是 GPS 坐标,Proximity 是(一些单位 - 英尺?秒?分钟?)
并且给定用户当前的 GPS 纬度/经度...
我想编写一个 SQL 查询,该查询将检索用户在这些行的“邻近”范围内的所有行。
还有诀窍:这必须在 SQLite 中工作,它只支持相当原始的数据类型。不作弊,不依赖 SQL Server(或其他提供更好地理空间功能的产品)。
有什么建议吗?
【问题讨论】:
你不能用一个简单的SQL来计算两点的距离,然后看看这是否小于这个距离?简单的欧几里得几何? @Thomas:两点之间的欧几里得距离沿着穿过地球的直线。这可能不是你想要的。 @dan04 地球的圆周比任何搜索半径都大,可以忽略不计。 100 英里到 99.88 英里,也就是大约 630 英尺,不到一个足球场。 【参考方案1】:这是一个用于 sqlite 的基于 C 的自定义函数 [从下面提到的链接复制]。这可以在 ios 应用程序中使用。它假设您有名为纬度和经度的列,并计算它们与您提供的任何纬度/经度坐标之间的差异。优秀的文章,按原样工作。
#define DEG2RAD(degrees) (degrees * 0.01745327) // degrees * pi over 180 static void distanceFunc(sqlite3_context *context, int argc, sqlite3_value **argv) // check that we have four arguments (lat1, lon1, lat2, lon2) assert(argc == 4); // check that all four arguments are non-null if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL || sqlite3_value_type(argv[3]) == SQLITE_NULL) sqlite3_result_null(context); return; // get the four argument values double lat1 = sqlite3_value_double(argv[0]); double lon1 = sqlite3_value_double(argv[1]); double lat2 = sqlite3_value_double(argv[2]); double lon2 = sqlite3_value_double(argv[3]); // convert lat1 and lat2 into radians now, to avoid doing it twice below double lat1rad = DEG2RAD(lat1); double lat2rad = DEG2RAD(lat2); // apply the spherical law of cosines to our latitudes and longitudes, and set the result appropriately // 6378.1 is the approximate radius of the earth in kilometres sqlite3_result_double(context, acos(sin(lat1rad) * sin(lat2rad) + cos(lat1rad) * cos(lat2rad) * cos(DEG2RAD(lon2) - DEG2RAD(lon1))) * 6378.1);
这定义了一个 SQL 函数 distance(Latitude1, Longitude1, Latitude2, Longitude2),返回距离(以公里为单位) 两点之间。
要使用此功能,请添加上面的代码 ... 和 然后在调用 sqlite3_open 后立即添加此行:
sqlite3_create_function(sqliteDatabasePtr, "distance", 4, SQLITE_UTF8, NULL, &distanceFunc, NULL, NULL);
…其中 sqliteDatabasePtr 是调用返回的数据库指针 到 sqlite3_open。
假设您有一个名为 Locations 的表,其中的列名为 纬度和经度(均为 double 类型),包含 度,然后你可以像这样在你的 SQL 中使用这个函数:
SELECT * FROM Locations ORDER BY distance(Latitude, Longitude, 51.503357, -0.1199)
此示例根据距离对数据库中的位置进行排序 距离伦敦眼,51.503357,-0.1199。
编辑:
原链接http://www.thismuchiknow.co.uk/?p=71已经失效,所以正如评论中提到的那样,你可以使用这个链接:https://web.archive.org/web/20160808122817/http://www.thismuchiknow.co.uk/?p=71来获取那个网页
【讨论】:
总是有wayback machine【参考方案2】:Haversine formula 是您想要的。使用简单的欧几里得距离公式是不够的,因为地球的曲率会影响两点之间的距离。
Creating a Store Locator with php, mysql & Google Maps 是一篇关于用 MySQL 实现这个解决方案的文章,但是 SQLite 不支持三角函数。
在 Stack Overflow 上查看 Calculating Great-Circle Distance with SQLite 中的答案,了解有关扩展 SQLite 函数的更多提示,以便您解决这个问题。
【讨论】:
【参考方案3】:您还知道有一个名为 Spatialite 的 SQLite 插件,它具有与 PostGIS 和 SQLServer 相同的功能?我假设您正在尝试在 iPhone 或浏览器或其他东西上使用 SQLLite。如果不是,我强烈推荐 spaceite。
【讨论】:
是的,正在做 iPhone。找到thismuchiknow.co.uk/?p=71,我要试试。以上是关于基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite的主要内容,如果未能解决你的问题,请参考以下文章