2011-01-29 17 views
12

autorización I tienen una base de datos con cerca de 1.800 filas, cada una tiene una columna lat y long, lo que estoy tratando de hacer, consulta en Google Maps V3 .getBounds El resultado es algo así como ((33.564398518424134, -79.38014701875002), (35.375726155241175, -76.08424858125002)) Lo que yo quiero hacer, es obtener todos los registros cuyo lat & lng en la base de datos está dentro de esos límites. ¿Alguna sugerencia?Obtener todos los registros de la base de datos MySQL que se encuentran dentro de Google Maps .getBounds?

Creo que tendría que extrapolar las otras 2 esquinas del mapa, ya que .getBounds solo contiene 2 puntos (supongo que 2 esquinas del mapa), y me gustaría estar dentro de los 4 puntos. Si lo hiciera terminaría con una matriz algo así como ... Ahora corrígeme si estoy equivocado, pero esto debería ser NW, NE, SW, SE, esquinas del mapa, en lat-lng.

33.564398518424134, -79.38014701875002 
33.564398518424134, -76.08424858125002 
35.375726155241175, -79.38014701875002 
35.375726155241175, -76.08424858125002 

Ok, así que si tengo estos datos, ¿cómo iba a construir una consulta para obtener las filas que están dentro de estas coordenadas? La tabla se llama tilistings - las columnas son lat y lng ... también si hay una manera más fácil, o estoy loco con mi metodología, no dude en hacérmelo saber.

Gracias

Respuesta

15

si de Google: ((a, b), (c, d))

SELECT * FROM tilistings WHERE lat > a AND lat < c AND lng > b AND lng < d

+1

Hmm yo pensamos que sería más difícil de lo que, gracias Estaba manera Overthinking éste –

+2

Hay muchas maneras de despellejar a un gato – bensiu

+1

v3 api. map.getBounds(). getNorthEast(); map.getBounds(). getSouthWest(); para obtener los objetos LatLng apropiados –

4

No he utilizado la API de Google, pero mi entendimiento es que si obtenga ((33.564398518424134, -79.38014701875002), (35.375726155241175, -76.08424858125002)) de regreso de una llamada a getBounds (33.564398518424134, -79.38014701875002) es la esquina suroeste y (35.375726155241175, -76.08424858125002) es el noreste. Lo digo porque creo que devuelven las esquinas del noreste y el sudoeste, y asumo que los puntos son latitud, longitud.

Si eso es correcto, entonces la consulta de Bensiu funcionaría. Normalmente, usar BETWEEN es más eficiente.

SELECT * FROM tilistings WHERE lat BETWEEN a AND c AND lng between b AND d 
20

Todas las respuestas anteriores solo funcionan para 1/4 del mundo!

W3t La respuesta de Tr3y estaba cerca, pero tenía un error (extra "<").

Todos ellos solo funcionan para EE. UU., Porque están en el hemisferio NORTE. No funcionan para el hemisferio sur, ni para los países del este (derecha de Greenwich).

Aquí hay una solución simple sin funciones o cosas complicadas.

las letras son los resultados en el orden en que las obtiene de map.getBounds() es decir, swlat, swlng, nelat, nelng = a, b, c, d.

SELECT * FROM tilistings WHERE 
(CASE WHEN a < c 
     THEN lat BETWEEN a AND c 
     ELSE lat BETWEEN c AND a 
END) 
AND 
(CASE WHEN b < d 
     THEN lng BETWEEN b AND d 
     ELSE lng BETWEEN d AND b 
END) 

u otra solución con y/o (puedes probarlo para la velocidad, no sé cómo ejecutar más de una vez en el banco de trabajo)

SELECT * FROM tilistings WHERE 
(a < c AND lat BETWEEN a AND c) OR (c < a AND lat BETWEEN c AND a) 
AND 
(b < d AND lng BETWEEN b AND d) OR (d < b AND lng BETWEEN d AND b) 

Ahora puede asignar la totalidad mundo :) Espero que alguien pueda marcar las respuestas anteriores como incorrectas, porque nos están haciendo perder mucho tiempo a millones de personas que aprenden como yo. Me pregunto cómo obtienen tantos votos cuando realmente no funcionan.

PD: ¡Las posibilidades de que el borde del píxel de su mapa coincida con el valor exacto de 15 decimales de las coordenadas son millones de veces menos que las posibilidades de perder un 3/4 entero del mundo!

+0

¡Hola! Probé esto, y funciona muy bien cuando nos alejamos, pero cuando nos acercamos a ubicaciones precisas, los resultados no son muy precisos. Estoy usando PHP y MySQL ... ¿Crees que hay pasos específicos que se deben tomar al calcular grandes números decimales en SQL –

+1

debe ser: swlat, swlng, nelat, nelng = a, b, c, d (intenté editar la respuesta , pero SO dijo que se deben cambiar al menos 6 caracteres) – psylosss

+0

Esta debería ser la respuesta aceptada. Gracias por esto. Era tan simple, sin embargo, me estaba sacando el pelo encima. –

0

No estoy seguro de que la afirmación anterior sea correcta. En primer lugar, creo que las esquinas son nulas, nulas, blandas, que no se desenrollan como se indicó anteriormente "swlat, swlng, nwlat, nwlng". En segundo lugar, creo que el Nelat siempre va a ser más alto que el brillo de la ventana (a menos que la ventana cubra uno de los polos geográficos que no estoy seguro de que sea posible con los mapas de Google).

Finalmente, si la ventana cubre la línea de fecha internacional (aproximadamente +/- 180lng) es decir, < b, seguramente debería ser "NO ENTRE BYD". ¿Tal vez alguien con más conocimiento especializado podría confirmarlo?

1

Esto funciona para mí:

$condition1 = $a < $c ? "lat > $a AND lat < $c" : "lat > $a OR lat < $c"; 
$condition2 = $b < $d ? "lon > $b AND lon < $d" : "lon > $d OR lon < $b"; 
$q = "SELECT * FROM tilistings WHERE ($condition1) AND ($condition2)"; 
1

Podemos encontrar resultar entre Maps.getBounds noreste y sudoeste y noreste latitud y longitud del suroeste de consulta mediante el siguiente.

consulta de búsqueda debe estar entre northEast.latitude Y southWest.latitude Y northEast.longitude Y southWest.longitude

$nelat=$_GET['nelat']-0.5; 
$nelng=$_GET['nelng']-0.5; 
$swlat=$_GET['swlat']-0.5; 
$swlng=$_GET['swlng']-0.5; 

$sql ="SELECT * FROM tablename where (CASE WHEN ".$nelat." < ".$swlat." 
    THEN s.latitude BETWEEN ".$nelat." AND ".$swlat." 
    ELSE s.latitude BETWEEN ".$swlat." AND ".$nelat." 
END) 
AND 
(CASE WHEN ".$nelng." < ".$swlng." 
     THEN s.longitude BETWEEN ".$nelng." AND ".$swlng." 
     ELSE s.longitude BETWEEN ".$swlng." AND ".$nelng." 
END)"; 
2

que ahora es demasiado tarde para el comentario, pero tal vez será útil para alguien Sergio unswer no es del todo correcto la consulta para el mundo entero tiene que mirar un poco diferente, si no me equivoco algo parecido a éste:

SELECT * FROM tilistings WHERE (sw_lat < ne_lat AND lat BETWEEN sw_lat AND ne_lat) OR (sw_lat > ne_lat AND (lat BETWEEN sw_lat AND 180 OR lat BETWEEN -180 AND ne_lat)) (sw_lon < ne_lon AND lon BETWEEN sw_lon AND ne_lon) OR (sw_lon > ne_lon AND (lon BETWEEN sw_lon AND 180 OR lon BETWEEN -180 AND ne_lon))

+0

A diferencia de las otras soluciones, esto funciona de manera consistente en todo el mundo para mí. ¡Gracias! –

1

Una versión ligeramente simplificada de la respuesta de Vladimir es trabajando perfectamente para mi

Tomando un área delimitada por un recuadro con un borde sur (sur), un borde occidental (oeste), un extremo norte (norte) y uno oriental (este). Estos pueden derivarse de Google Map .getBounds que proporcionan esquina suroeste y esquina noreste: solo necesita las dos esquinas, ya que describen por completo el recuadro delimitador cuadrado.

En este ejemplo, nuestra tabla de base de datos se llama ubicaciones y contiene una columna de latitud y longitud.

SELECT * FROM locations WHERE 
(latitude BETWEEN south AND north) AND 
((west < east AND longitude BETWEEN west AND east) OR 
(west > east AND (longitude BETWEEN west AND 180 OR longitude BETWEEN -180 AND east))) 

Esto funciona basado en el hecho de que sólo tenemos que tener en cuenta para el cruce de 180/-180 línea de longitud como un caso especial - es decir, cuando la longitud occidental es un valor mayor que la longitud del este. En cualquier caso en que no crucemos esa línea, la longitud occidental siempre será menor que la longitud este.

Con respecto a la latitud, el borde sur siempre tendrá un valor inferior al de la latitud norte, ya que no existe el concepto de envolverse alrededor de los polos. Para cubrir un área sobre el polo norte, por ejemplo, simplemente tenemos todas las longitudes (es decir, de -180 a 180) y la latitud desde el límite sur hasta +90.

+0

^^ ESTA es la respuesta correcta. Funciona perfectamente y rápidamente. Gracias @Fat Monk. – freeworlder

1

Eche un vistazo a los nuevos datos espaciales y funciones disponibles en MySQL 5.7, ahora también para InnoDB.

Utilizando los ejemplos anteriores, se necesitan aproximadamente 1s para una tabla con 1 millón de registros para obtener las ubicaciones dentro de un cuadro delimitador determinado.

Con ST_Within() y ST_MakeEnvelope() y el índice espacial correcto, obtengo el resultado en menos de 0.01s.

0

Desde mi Gist https://gist.github.com/jesuGMZ/0d7f38d80e2f67d0bc4b7fb620345344

Tener MySQL> 5,7 con una tabla que contiene un tipo de columna PUNTO nombrado location y la siguiente respuesta de Google Maps:

"geometry": { 
    "bounds": { 
     "northeast": { 
      "lat": 40.5638447, 
      "lng": -3.5249115 
     }, 
     "southwest": { 
      "lat": 40.3120639, 
      "lng": -3.8341618 
     } 
    }, 
    //.... 

puede realizar una consulta SQL para recuperar todas sus ubicaciones contiene en ese límite como este:

SELECT * FROM my_table 
WHERE Contains(
    ST_MakeEnvelope(
    ST_GeomFromText('POINT(40.5638447 -3.5249115)'), 
    ST_GeomFromText('POINT(40.3120639 -3.8341618)') 
), 
    location 
); 

Considere la posibilidad de indexar la ubicación para mejorar el rendimiento de sus consultas, si corresponde. Además, es posible usar Within en lugar de Contains cambiando el orden de los parámetros.

Enlaces de interés:

Cuestiones relacionadas