简体   繁体   中英

MySQL distance and min with group by

I have the following query:

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

This appears to be working fine but the problem I'm having is that since I'm grouping by user_id, and there and that user_id isn't unique in the table, I might and do get the closest distance, but not always the city and state_id of that distance (since there are multiple). Results:

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

If I add min (distance) I get weird results. Why?

You could use a filtering join, like:

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...)

If speed is an issue, you can use the MySQL variable trick. This is faster but non-portable (perhaps not even to future MySQL versions.)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM