我正在建立一个系统,用户可以使用邮政编码进行搜索(很快就会有多个邮政编码),每个“工作”最多可以有三个不同的位置。我需要返回最低距离作业的ID,以及计算的距离和作业的所有其他字段。
我可以计算工作的距离。我甚至可以为每份工作返回一个结果。
但我无法返回每个作业的最低距离结果。
我在这里整理了一个SQL小提琴:http://sqlfiddle.com/#!2/03b2c/10
示例数据:
输入:SET @user_lat = 44.053575, @user_lng = -123.086493, @range = 50;
ID JOB_ID LATITUDE LONGITUDE DISTANCE
9 1 44.063716888428 -123.08470916748 0
8 1 44.052070617676 -123.086753845215 0.81
7 1 44.035049438477 -123.047355651855 2.71
10 2 44.059913635254 -123.017936706543 3.32
11 2 44.045707702637 -122.930877685547 7.73
13 3 45.480751037598 -122.642738342285 100.21
小组结果 - 每行都可以,但不是最近的距离。
ID JOB_ID LATITUDE LONGITUDE DISTANCE
7 1 44.035049438477 -123.047355651855 2.71
10 2 44.059913635254 -123.017936706543 7.73
ROUND( [math], 2 ) AS distance -- (full query below)
...
GROUP BY job_id
HAVING distance < @range
ORDER BY distance ASC;
GROUP和Min()结果: - 正确返回最低距离,但没有正确的ID。
ID JOB_ID LATITUDE LONGITUDE DISTANCE
7 1 44.035049438477 -123.047355651855 0
10 2 44.059913635254 -123.017936706543 3.32
MIN( ROUND( [math], 2 ) ) AS distance
...
GROUP BY job_id
HAVING distance < @range
ORDER BY distance ASC;
__
我需要的是: - 返回最低距离,ID与该距离匹配。
ID JOB_ID LATITUDE LONGITUDE DISTANCE
9 1 44.035049438477 -123.047355651855 0
11 2 44.059913635254 -123.017936706543 3.32
__
完整查询群组结果示例
set
@user_lat = 44.063717,
@user_lng = -123.084706,
@range = 2000;
-- Filter by distance, displaying the nearest location of each job in miles
select
*,
-- We can use min() here to get the lowest distance, but this does not affect the ID returned!
-- min( ... ) as distance
ROUND(3956 * 2 * ASIN(SQRT(POWER(SIN( (@user_lat - abs(loc.latitude)) * pi()/180 / 2),2) + COS(@user_lat * pi()/180 ) * COS( abs(loc.latitude) * pi()/180) * POWER(SIN((@user_lng - loc.longitude) * pi()/180 / 2), 2) )), 2)
as distance
from `locations` loc
group by job_id
having distance < @range
order by distance asc;
答案 0 :(得分:2)
因为它是mysql,你可以利用它的特殊分组实现,从而得到一个非常简单的查询:
select * from (
select *,
ROUND(3956 * 2 * ASIN(SQRT(POWER(SIN( (@user_lat - abs(loc.latitude)) * pi()/180 / 2),2) + COS(@user_lat * pi()/180 ) * COS( abs(loc.latitude) * pi()/180) * POWER(SIN((@user_lng - loc.longitude) * pi()/180 / 2), 2) )), 2) as distance
from locations
order by distance) loc
group by job_id
答案 1 :(得分:1)
我暂时忽略了范围...
如果distance()是一个函数(很容易构造这样的东西)那么查询可能看起来像这样......
SELECT x.*
, distance(x.latitude,x.longitude,@user_lat,@user_lng)
FROM
( SELECT job_id
, MIN(distance(latitude,longitude,@user_lat,@user_lng)) min_distance
FROM locations
GROUP
BY job_id
) y
ON job_id = x.job_id
AND y.min_distance = distance(x.latitude,x.longitude,@user_lat,@user_lng);