我的查询的基本结构是:
profiles
表locations
表,其中只包含(profile_id,location_id)对每个配置文件都分配给一个或多个位置,我尝试做的是搜索配置文件,并按距离到位置坐标的顺序返回它们。我的查询是(仅包括相关部分)如下:
location_assignment
(选择行中的grosstastic事件将SELECT *,
(3959*acos(cos(radians(30.292424))*cos(radians(lat))*cos(radians(lng)-
radians(-97.73856))+sin(radians(30.292424))*sin(radians(lat)))) AS distance,
`profiles`.`name` as profilename,
`profiles`.`profile_id` as profile_id
FROM (`profiles`)
JOIN `location_assignment`
ON `profiles`.`profile_id` =`location_assignment`.`profile_id`
JOIN `locations`
ON `location_assignment`.`location_id` = `locations`.`location_id`
HAVING `distance` < 50
ORDER BY `distance`
LIMIT 3"
表中的lat / lng字段转换为距给定输入lat / lng的距离
但是,我的查询会在结果中多次显示配置文件,对于分配给他的每个位置。我希望每个配置文件只出现一次,其中包含距离最短的位置信息。
我的下意识反应是使用locations
,但我想确保获得与输入坐标的距离最小的位置。
答案 0 :(得分:2)
去长角牛!
让我们从位置表中找到正确的行开始。
SELECT DISTINCT location_id
FROM locations
ORDER BY your_spherical_cosine_law_distance_formula
LIMIT 1
这会获得唯一的位置ID。
现在,您希望将其用作子查询以获取相应的配置文件行。你喜欢这样:
SELECT whatever
FROM (
SELECT DISTINCT location_id
FROM locations
ORDER BY your_spherical_cosine_law_distance_formula
LIMIT 1
) AS one
JOIN location_assignment AS la ON one.location_id = la.location_id
JOIN profiles AS p on p.profile_id =la.profile_id
这应该为您提供适当的配置文件行列表,没有重复。
你没有提出这个问题,但我希望你没有太多的位置行。您正在使用的查询必须扫描整个表格,并为每一行进行大量数学运算。您的HAVING
条款确实无济于事。为了加快速度,您需要将距离搜索与边界矩形搜索相结合。这可能有所帮助。 http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/
答案 1 :(得分:1)
我认为您应该将MIN()
函数添加到距离计算中,以获得每个配置文件最近位置的距离。另外,按个人资料信息添加GROUP BY
。
(我知道MySQL允许返回不在GROUP BY
中的列,但这不是我要求的,所以我从*
中删除了SELECT
。
SELECT MIN(3959*acos(cos(radians(30.292424))*cos(radians(lat))*cos(radians(lng)-
radians(-97.73856))+sin(radians(30.292424))*sin(radians(lat)))) AS distance,
`profiles`.`name` as profilename,
`profiles`.`profile_id` as profile_id
FROM (`profiles`)
JOIN `location_assignment`
ON `profiles`.`profile_id` =`location_assignment`.`profile_id`
JOIN `locations`
ON `location_assignment`.`location_id` = `locations`.`location_id`
GROUP BY `profiles`.`name`, `profiles`.`profile_id`
HAVING `distance` < 50
ORDER BY `distance`
LIMIT 3"