如何在相等的桶中按距离排序?

How to sort by distance in equal buckets?

我们的产品的用户评论具有以下内容:

  1. 查看说明
  2. 撰写评论的日期
  3. 撰写评论的城市

我们这里有两个表:

1) 评论(列:描述 (varchar)、日期 (DateTime)、CityId (int))

2) 城市(列:Id (int)、名称 (varchar)、纬度、经度)

我们想要对这些用户评论进行排序,如果输入是任何给定的城市,比如说城市 'C',输出排序顺序应该是:

解决此问题的一种简单方法 is:Just 在运行时执行并逐个获取这些公里范围内的城市,然后审查这些城市,但速度太慢。此外,我们将多次执行相同的操作。为了避免重新计算,我们可以为每个城市保存附近桶城市的信息,但不确定是否理想。

有没有更简单、更有效的方法来解决这个问题,即 kat/long 或任何其他方法?

您可以使用 Haversine Formula; see Haversine implementation 编写可直接在您的查询中使用的 MySQL 函数来检索按距离排序的评论。

在下面的查询中(也在 SQL Fiddle 中)我使用了一个更简单的公式来说明查询将如何使用 "Los Angeles" (789) 作为给定城市:

select *
from (
  select
    r.*,
    sqrt(power(g.lat - c.lat, 2) + power(g.lng - c.lng, 2)) as dist -- simple dist
  from reviews r
  join cities c on c.id = r.cityid -- city the review belongs to
  join cities g on g.id = 789 -- given city as input
) x
order by dist

请注意 table cities 加入了两次:第一次作为评论所属的城市,然后作为给定的 [base] 城市。这使我们能够计算距离。

结果:

description  recorded             cityid  dist   
-----------  -------------------  ------  -------
review 4     2019-01-01 07:34:56  789     0      
review 2     2019-01-01 07:34:56  456     5.65685
review 3     2019-01-01 07:34:56  456     5.65685
review 1     2019-01-01 07:34:56  123     6.32456

供参考,这是我使用的数据脚本:

create table reviews (
  description varchar(100),
  recorded datetime,
  cityid int
);

insert into reviews (description, recorded, cityid) values 
  ('review 1', '2019-01-01 12:34:56', 123),
  ('review 2', '2019-01-01 12:34:56', 456),
  ('review 3', '2019-01-01 12:34:56', 456),
  ('review 4', '2019-01-01 12:34:56', 789);

create table cities (
  id int,
  name varchar(20),
  lat double,
  lng double
);

insert into cities (id, name, lat, lng) values 
  (123, 'Chicago', 10, 11),
  (456, 'Indianapolis', 12, 9),  
  (789, 'Los Angeles', 8, 5);