MySQL的距离和min与group by

时间:2012-07-28 09:21:58

标签: mysql sql group-by spatial

我有以下查询:

SELECT TeacherLocation.user_id, TeacherLocation.city, TeacherLocation.state_id, 
TeacherLocation.latitude, TeacherLocation.longitude,    

3959 * acos( cos( radians(40.76332092) ) * cos( radians( TeacherLocation.latitude ) )* 
cos( radians(   TeacherLocation.longitude ) - radians(-73.98623657) ) + sin(       
radians(40.76332092) ) * 
sin( radians( TeacherLocation.latitude ) )  ) AS distance 

FROM teacher_locations AS TeacherLocation

GROUP BY TeacherLocation.user_id
HAVING distance > 0
ORDER BY distance ASC LIMIT 0, 100

这似乎工作正常,但我遇到的问题是,因为我按user_id分组,并且那个user_id在表中不是唯一的,我可能并且确实得到最近的距离,但不是总是那个距离的城市和state_id(因为有多个)。结果:

user_id     city            stateId Lat             Long            Distance
83224   NEW YORK    33  40.751091   -73.99469757    0.954064642293979
87336   NEW YORK    33  40.751091   -73.99469757    0.954064642293979
87850   NEW YORK    33  40.751091   -73.99469757    0.954064642293979
86822   NEW YORK    33  40.751091   -73.99469757    0.954064642293979

如果我添加min(距离),我会得到奇怪的结果。为什么呢?

1 个答案:

答案 0 :(得分:2)

您可以使用过滤联接,例如:

select  *
from    teacher_locations tl
join    (
        select  user_id
        ,       min(... distance formula here...) as MinDistance
        from    teacher_location
        group by
                user_id
        ) filter
on      filter.user_id = tl.user_id
        and filter.MinDisance = tl.(... distance formula here...)

如果速度是个问题,你可以使用MySQL变量技巧。这是更快但不可移植的(甚至可能不适用于未来的MySQL版本。)

select  *
from    (
        select  @rn := if(user_id = @lastuserid, 1, @rn+1) as rn
        ,       @lastuserid := user_id
        ,       tl.*
        from    TeacherLocation tl
        cross join
               (select @rn := 0, @lastuserid := -1) as init
        order by
                tl.user_id
        ,       tl.distance desc
        ) as SubQueryAlias
where   rn = 1

Example at SQL Fiddle, you'll have to expand the distance calculation yourself.