7

在给定初始位置的情况下,我必须获得一个 SQLite SQL 语句,以便按最近的纬度和经度坐标进行排序。

这是我在 sqlite 数据库中的表的示例语句:

SELECT id, name, lat, lng FROM items

EXAMPLE RESULT: 1, Museu, 41375310.0, 2175970.0

我必须用 SQLite 和那个表来实现这一点。我不能使用其他技术,因为这是我无法更改的现有 SQlite 数据库。

有没有办法通过 Android 和 SQlite 实现这一点?我检查了很多stackoverflow帖子,但没有找到实现这一目标的方法

谢谢

4

5 回答 5

22
SELECT * AS distance FROM items ORDER BY ABS(location_lat - lat) + ABS(location_lng - lng) ASC

这应该在 MySQL 中对距离上的项目进行粗略排序,并且应该在 SQLite 中工作。
如果您需要更精确地对它们进行排序,您可以尝试使用勾股定理 (a^2 + b^2 = c^2) 来获得准确的距离。

于 2012-10-01T12:02:34.167 回答
22

Darkwater 的答案几乎是正确的。为了正确,您需要使用差异的平方。由于 Square 函数在 SqlLite 上不可用,因此您需要将差异乘以它们自己。无需计算平方根。

SELECT * AS distance FROM items ORDER BY ((location_lat-lat)*(location_lat-lat)) + ((location_lng - lng)*(location_lng - lng)) ASC
于 2015-09-03T00:33:09.490 回答
14

克里斯提出的解决方案:

SELECT * AS distance FROM items ORDER BY ((location_lat-lat)*(location_lat-lat)) + ((location_lng - lng)*(location_lng - lng)) ASC

当我们靠近赤道时是正确的。为了让它在其他纬度正常工作,我建议:

SELECT * AS distance FROM items ORDER BY ((location_lat-lat)*(location_lat-lat)) + ((location_lng - lng)*(location_lng - lng)* cos_lat_2 ) ASC

我们必须预先计算:

cos_lat_2 = cos(location_lat * PI / 180) ^ 2

问题:

如果我们在赤道并且我们在经度上移动 1 度(东或西),我们在 40,000 公里的圆周上移动,代表距离为 40.000 / 360。如果我们在纬度上移动 1 度(北或南),我们在一个穿过两极的圆上这样做,这也涉及 40.000 / 360 的距离(考虑到地球是一个球体)。

但是,如果我们在英格兰南部,纬度为 50°,并且我们在经度上移动 1 度(东或西),我们会在 50 度纬线上进行,它的周长小于赤道。距离是 perimeter_parallel_50 / 360。计算这个周长很简单:perimeter_parallel_50 = cos (50) * 2 * PI * EARHT_RADIUS = 0.64 * 40,000 km。如果我们向南或向北移动 1 度,则看不到这种距离的减少。我们移动的圆周仍有 40,000 公里的周长。

解决方案:

由于 location_lat 是一个预先知道的值,我们可以预先计算 cos(location_lat) 的值,以便将其用作比例因子,使经度和纬度的位移相等。此外,我们预先平方它以避免必须将其乘以两次。

笔记:

这仍然是一个近似值,在大距离移动时会给出错误的结果,尤其是在两极附近和穿过 180 度子午线时。

于 2016-09-02T17:54:17.833 回答
4

如果你知道,1 度的纬度大约是 111111 米,1 度的经度是 111111*cos(latitude) 米,那么你可以很容易地得到一个特定正方形内的所有地方。

SELECT * FROM items WHERE latitude BETWEEN %f AND %f AND longitude BETWEEN %f AND %f

这个查询非常快,即使有数百万行。但不要忘记为纬度和经度创建索引:

CREATE INDEX position ON items (latitude, longitude)

我在 Objective-C 中使用它来获取当前位置周围 3 公里内的所有景点:

double latDist = 1.0 / 111111.0 * 3.0;
double lonDist = 1.0 / ABS(111111.0*cos(location.coordinate.latitude)) * 3.0;

FMResultSet *results = [database executeQueryWithFormat:@"SELECT * FROM items WHERE latitude BETWEEN %f AND %f AND longitude BETWEEN %f AND %f", location.coordinate.latitude - latDist, location.coordinate.latitude + latDist, location.coordinate.longitude - lonDist, location.coordinate.longitude + lonDist];

您现在可以计算确切的距离并对结果进行排序...

于 2014-02-25T19:36:11.833 回答
3

如果您能够加载记录;将它们转换为 Locations ,然后使用我推荐的 distanceTo 函数,但是......

您可以使用简单的 SQL 来估计两点之间的距离,这里清楚地列出了各种方法。您要比较的点越远,如果您使用简单的计算,您的值就会变得越来越不正确

如果您自己计算这些东西并且您的位置可以在任何地方,那么如果您比较国际日期变更线周围的位置,您可能需要注意环绕的值。

于 2012-10-01T12:08:10.833 回答