从WHERE结果中获取mysql SELECT MIN

时间:2014-06-25 08:42:17

标签: mysql

我有一张桌子,上面有几条路线,其中有一些由经纬度定义的严重点。

表名:route_path

 |id_route  |id_point| lat        | lng       |
 |hhVFlBFA0M|     328| 48.90008   | 18.0233   |
 |hhVFlBFA0M|     329| 48.90003   | 18.0268   |
 |hhVFlBFA0M|     330| 48.89997   | 18.02856  |
 |hhVFlBFA0M|     331| 48.89991   | 18.02857  |
 |hhVFlBFA0M|     332| 48.89986   | 18.02862  |
 |hhVFlBFA0M|     333| 48.89982   | 18.02869  |
 |hhVFlBFA0M|     334| 48.89981   | 18.02878  |
 |hhVFlBFA0M|     335| 48.89981   | 18.02886  |
 |hhVFlBFA0M|     336| 48.89956   | 18.02925  |
 |hhVFlBFA0M|     337| 48.89914   | 18.02972  |
 |hhVFlBFA0M|     338| 48.8986177 | 18.0302365|
 |3toCyDGVV2|       1| 48.134166  | 17.1051961|
 |3toCyDGVV2|       2| 48.13417   | 17.1052   |
 |3toCyDGVV2|       3| 48.13344   | 17.10559  |
 |3toCyDGVV2|       4| 48.13298   | 17.10609  |
 |3toCyDGVV2|       5| 48.13221   | 17.10699  |
 |3toCyDGVV2|       6| 48.132     | 17.10806  |
 |3toCyDGVV2|       7| 48.13193   | 17.10997  |
 |3toCyDGVV2|       8| 48.13203   | 17.1109   |  
 |3toCyDGVV2|       9| 48.132     | 17.1 112  |
 |3toCyDGVV2|      10| 48.13181512| 17.1112   |  
 |3toCyDGVV2|      11| 48.13181   | 17.10806  |
 |3toCyDGVV2|      12| 48.13181   | 17.10806  |
 |3toCyDGVV2|      13| 48.13197   | 17.10399  |
 |3toCyDGVV2|      14| 48.13199   | 17.10352  |
 |3toCyDGVV2|      15| 48.1323    | 17.10328  |

到目前为止,我可以选择一条路线中所有可以容忍的距离,然后循环找到最小距离点。

SELECT * FROM route_path 
WHERE 
(((lat < $start_lat + $tolerance) AND 
(lat > $start_lat - $tolerance)) AND 
((lng < $start_lng + $tolerance) AND 
(lng > $start_lng - $tolerance)))

所以这将导致每条路线的几行(id_point s),然后我需要循环,同时找到最小值。

我怎样才能从每条路线中找出选择一行(一个id_point),距离start lat和lng的距离最小,考虑到这个距离不超过某个值。

没有循环的任何sql请求建议。

基本上我需要类似的东西,但当然不能在WHERE

之后使用MIN
SELECT * FROM route_path WHERE **MIN(**(((lat < $start_lat + $tolerance) AND (lat > $start_lat - $tolerance)) AND ((lng < $start_lng + $tolerance) AND (lng > $start_lng - $tolerance)))**)**

1 个答案:

答案 0 :(得分:0)

有几种方法可以计算2点之间的距离。效率最高的可能是使用专为此设计的空间数据类型,并为此提供索引。我还没有这方面的经验,所以如果你想改变你的数据库使用这些我只会指出你以前的问题来获得基础知识(接受的答案涵盖它): -

Fastest Way to Find Distance Between Two Lat/Long Points

如果您想使用当前的桌子,那么您可以通过以下计算获得2点之间的距离: -

111.045 * DEGREES(ACOS(COS(RADIANS(lat_point_1))
                 * COS(RADIANS(lat_point_2))
                 * COS(RADIANS(long_point_1) - RADIANS(long_point_2))
                 + SIN(RADIANS(lat_point_1))
                 * SIN(RADIANS(lat_point_2))))

(取自here)。

如果你想知道到达起点的特定路线上的最近点你可以使用它(不需要乘以111.045,除非你关心的是实际距离而不是它是最接近的距离): -

SELECT id_route,
        id_point,
        lat,
        lng,
        DEGREES(ACOS(COS(RADIANS($start_lat))
                 * COS(RADIANS(lat))
                 * COS(RADIANS($start_lng) - RADIANS(lng))
                 + SIN(RADIANS($start_lat))
                 * SIN(RADIANS(lat)))) AS distance_in_km
FROM route_path
WHERE id_route = 'hhVFlBFA0M'
ORDER BY distance_in_km 
LIMIT 1

如果你想知道到达起点的每条路线上的最近点,你会计算每条路线上的最近点,然后将其连接到原始表格,该表格的距离与最小距离相匹配(这将导致如果单条路线上的2点完全与起点的距离相同

,则会出现问题
SELECT route_path.id_route,
        route_path.id_point,
        route_path.lat,
        route_path.lng
FROM route_path
INNER JOIN
(
    SELECT id_route,
            MIN(DEGREES(ACOS(COS(RADIANS($start_lat))
                     * COS(RADIANS(lat))
                     * COS(RADIANS($start_lng) - RADIANS(lng))
                     + SIN(RADIANS($start_lat))
                     * SIN(RADIANS(lat))))) AS distance_in_km
    FROM route_path
    GROUP BY id_route
) sub0
ON route_path.id_route = sub0.id_route
AND DEGREES(ACOS(COS(RADIANS($start_lat))
                     * COS(RADIANS(lat))
                     * COS(RADIANS($start_lng) - RADIANS(lng))
                     + SIN(RADIANS($start_lat))
                     * SIN(RADIANS(lat)))) = sub0.distance_in_km