如何在相等的桶中按距离排序?
How to sort by distance in equal buckets?
我们的产品的用户评论具有以下内容:
- 查看说明
- 撰写评论的日期
- 撰写评论的城市
我们这里有两个表:
1) 评论(列:描述 (varchar)、日期 (DateTime)、CityId (int))
2) 城市(列:Id (int)、名称 (varchar)、纬度、经度)
我们想要对这些用户评论进行排序,如果输入是任何给定的城市,比如说城市 'C',输出排序顺序应该是:
- 针对距城市 'C' 0 到 'X' 公里以内的城市撰写的评论,然后是
- 针对 'X' 至城市 'C'“2X”公里的城市撰写的评论,其次是
- 为“2X”到“3X”公里内的城市撰写的评论,依此类推,直到城市结束。
解决此问题的一种简单方法 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);
我们的产品的用户评论具有以下内容:
- 查看说明
- 撰写评论的日期
- 撰写评论的城市
我们这里有两个表:
1) 评论(列:描述 (varchar)、日期 (DateTime)、CityId (int))
2) 城市(列:Id (int)、名称 (varchar)、纬度、经度)
我们想要对这些用户评论进行排序,如果输入是任何给定的城市,比如说城市 'C',输出排序顺序应该是:
- 针对距城市 'C' 0 到 'X' 公里以内的城市撰写的评论,然后是
- 针对 'X' 至城市 'C'“2X”公里的城市撰写的评论,其次是
- 为“2X”到“3X”公里内的城市撰写的评论,依此类推,直到城市结束。
解决此问题的一种简单方法 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);