Chris提出的解决方案是:
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_lat_2 = cos(location_lat * PI / 180) ^ 2
问题:
如果我们在赤道上,向东或西移动一度经度,我们将沿着周长为40,000公里的圆形移动,代表了40,000/360的距离。如果我们向南或北移动一度纬度,则会在穿过两极的圆上移动,这也涉及到40,000/360的距离(考虑到地球是一个球体)。
但是,如果我们在英格兰南部,纬度为50度,并且我们向东或西移动一度经度,则我们将在第50平行线上移动,它的周长比赤道小。距离是perimeter_parallel_50/360。计算这个周长很简单:perimeter_parallel_50 = cos (50) * 2 * PI * EARTH_RADIUS = 0.64 * 40,000公里。如果我们向南或北移动一度,这种距离的减少是看不见的。我们移动的周长仍然具有40,000公里的周长。
解决方法:
由于location_lat是预先知道的值,因此我们可以预先计算cos(location_lat)的值,以便它可以用作缩放因子,使经度和纬度的位移相等。此外,我们对其进行预平方,以避免必须两次乘以它。
注意:
这仍然是一个近似值,在移动较大距离时,特别是在靠近极点和穿越180度子午线时,它将给出错误的结果。