sqlite - 基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite

标签 sqlite geospatial

给定一个包含三个字段的数据库:

纬度 经度 接近度

Lat 和 Long 是 GPS 坐标,Proximity 是(某个单位 - 英尺?秒?分钟?)

并给定用户当前的 GPS 纬度/经度...

我想编写一个 SQL 查询来检索用户在这些行的“邻近”范围内的所有行。

诀窍:这必须在 SQLite 中工作,它只支持相当原始的数据类型。不要欺骗和依赖 SQL Server(或其他提供更好地理空间功能的产品)。

有什么建议吗?

最佳答案

这是 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);
}

This defines an SQL function distance(Latitude1, Longitude1, Latitude2, Longitude2), which returns the distance (in kilometres) between two points.

To use this function, add the code above ... and then add this line immediately after you call sqlite3_open:

sqlite3_create_function(sqliteDatabasePtr, "distance", 4, SQLITE_UTF8, NULL, &distanceFunc, NULL, NULL);

…where sqliteDatabasePtr is the database pointer returned by your call to sqlite3_open.

Assuming you have a table called Locations, with columns called Latitude and Longitude (both of type double) containing values in degrees, you can then use this function in your SQL like this:

SELECT * FROM Locations ORDER BY distance(Latitude, Longitude, 51.503357, -0.1199)

This example orders the locations in your database based on how far away they are from the London Eye, which is at 51.503357, -0.1199.

编辑:

原文链接http://www.thismuchiknow.co.uk/?p=71已经死了,所以正如评论中提到的那样,您可以使用此链接:https://web.archive.org/web/20160808122817/http://www.thismuchiknow.co.uk/?p=71获取该网页

关于sqlite - 基于纬度/经度查询附近兴趣点的 SQL 查询 - SQLite,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3168904/

相关文章:

sql - 如何将带时区的日期时间插入 SQLite?

android - Android 平台是否支持 SpatiaLite?

google-maps - Mongodb 地理空间索引与 GoogleMaps 方向服务

python - 从 sqlite 查询中删除格式

sqlite - 如何使用 clojure.java.jdbc 插入包含时间戳值的行?

Python sqlite3 查询在终端中有效,但在应用程序中无效

java - 数据库助手类?

mongodb - $geoNear - mongodb 聚合中的 $maxDistance 不起作用

sql-server - 我将如何概括多个相邻的多边形?

sql - 如何扩展此SQL查询以找到k个最近的邻居?