我们对具有以下内容的产品进行用户评论:
我们在这里有两个表:
1)评论(列:说明(varchar),日期(DateTime),CityId(int))
2)城市(列:Id(int),名称(varchar),纬度,经度)
我们要对这些用户评论进行排序,以便如果输入是任何给定的城市,假设城市为“ C”,则输出排序顺序应为:
解决此问题的一种简单方法是:仅在运行时执行此操作,然后逐个获取这些公里范围内的城市,然后再进行检查,但这太慢了。另外,我们将多次执行相同的操作。为了避免重新计算,我们可以为每个城市保存附近桶市的信息,但不确定是否理想。
有没有更简单,更有效的方法来解决此问题,例如通过kat / long或其他任何方法?
答案 0 :(得分:1)
您可以使用Haversine Formula来检索按距离排序的评论;请参见Haversine implementation编写可直接在查询中使用的MySQL函数。
在下面的查询中(也在SQL Fiddle中),我使用了一个更简单的公式来说明如何使用“洛杉矶”(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
请注意,表cities
被连接了两次:首先是评论所属的城市,然后是给定的[基本]城市。这样我们就可以计算距离。
结果:
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);