Problema al obtener zips en radio a través de MySQL


9

Tengo una tabla de códigos postales que incluye el lat central, lng para cada código postal. Lo uso para obtener una lista de códigos postales dentro de un radio de milla dado desde cualquier punto arbitrario.

Se me ocurrió que, solo porque el punto central de un zip no esté dentro de un radio dado, no significa que el zip no esté dentro del radio.

Utilicé mis habilidades artísticas súper avanzadas para ilustrar el punto aquí:

ingrese la descripción de la imagen aquí

  • Las manchas de rayas verdes representan los códigos postales A, B y C.

  • Las manchas rojas son los centros geográficos de cada código postal.

  • El punto fucsia es la ubicación de destino, y ..

  • El círculo azul abultado está a un radio de 1 milla de la ubicación del objetivo

Si ejecuto una consulta para todos los códigos postales dentro de un radio de 1 milla de la mancha rosa, solo se devolverán los códigos postales B y C ya que el punto central para el zip A no está dentro del radio de una milla, aunque la mancha rosa en sí está claramente en el código postal A.

SELECT *,
        p.distance_unit
                 * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                 * COS(RADIANS(z.y))
                 * COS(RADIANS(p.longpoint) - RADIANS(z.x))
                 + SIN(RADIANS(p.latpoint))
                 * SIN(RADIANS(z.y)))) AS dist
  FROM standard_zip AS z
  JOIN (   /* these are the query parameters */
        SELECT  $lat  AS latpoint,  $lng AS longpoint,
                $miles AS radius,      69 AS distance_unit
    ) AS p ON 1=1
  WHERE z.y
     BETWEEN p.latpoint  - (p.radius / p.distance_unit)
         AND p.latpoint  + (p.radius / p.distance_unit)
    AND z.x
     BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
         AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
  ORDER BY dist

¿Cómo diablos escribo una consulta que incluirá zip A en los resultados?

Tengo acceso a espacial / geometría para cada código postal que puedo agregar a la tabla si es necesario, pero no tengo idea de cómo lo usaría para este propósito en MySQL.


Editar : Pasé un día leyendo los documentos de Oracle y MySQL para datos espaciales y logré convertir mis datos espaciales a MySQL con éxito . ¿Cómo hago para escribir una consulta similar que use la columna de geometría en lugar de la longitud y la longitud? Estoy usando datos 2D ... la geometría son solo polígonos y multipolígonos ...

Creo que lo descubrí ...

select
  *
from
  (
    select
      MIN(st_distance(geom, POINT(-82.765136, 28.0914015))) * 69 as miles,
      zip
    from
      zip_spatial
    group by
      zip
    order by
      miles asc
  ) d
where
  d.miles < 5

Dejaré la recompensa abierta por ahora en caso de que alguien tenga una solución mejor y más eficiente.

Respuestas:


7

De la indexación y consulta de datos espaciales en Oracle en la Guía del desarrollador espacial de Oracle® 11g, versión 2 (11.2):

Consultar datos espaciales

Spatial utiliza un modelo de consulta de dos niveles con operaciones de filtro primario y secundario para resolver consultas espaciales y uniones espaciales. El término de dos niveles indica que se realizan dos operaciones distintas para resolver consultas. Si se realizan ambas operaciones, se devuelve el conjunto de resultados exactos.

No puede agregar un nombre de enlace de base de datos (dblink) al nombre de una tabla espacial en una consulta si se define un índice espacial en esa tabla.

Consulta espacial

En un índice espacial de árbol R, cada geometría está representada por su rectángulo de límite mínimo (MBR). Considere la siguiente capa que contiene varios objetos en la Figura 1. Cada objeto está etiquetado con su nombre de geometría (geom_1 para la cadena de línea, geom_2 para el polígono de cuatro lados, geom_3 para el polígono triangular y geom_4 para la elipse), y el MBR alrededor de cada objeto está representado por una línea discontinua.

Figura 1 Geometrías con MBR

Descripción de "Figura 1 Geometrías con MBR"

Una consulta espacial típica es solicitar todos los objetos que se encuentran dentro de una ventana de consulta, es decir, una cerca o ventana definida. Una ventana de consulta dinámica se refiere a un área rectangular que no está definida en la base de datos, pero que debe definirse antes de usarse. La Figura 2 muestra las mismas geometrías que en la Figura 1, pero agrega una ventana de consulta representada por el cuadro de línea de puntos gruesa.

Figura 2 Capa con una ventana de consulta

Descripción de "Figura 2 Capa con una ventana de consulta"

En la Figura 2, la ventana de consulta cubre partes de las geometrías geom_1 y geom_2, así como parte del MBR para geom_3 pero ninguna de la geometría real de geom_3. La ventana de consulta no cubre ninguna parte de la geometría geom_4 o su MBR.

Operador de filtro primario

El operador SDO_FILTER implementa la parte del filtro primario del proceso de dos pasos involucrado en el modelo de procesamiento de consultas de Oracle Spatial. El filtro primario usa los datos del índice para determinar solo si un conjunto de pares de objetos candidatos puede interactuar. Específicamente, el filtro primario verifica si los MBR de los objetos candidatos interactúan, no si los objetos interactúan. La sintaxis del operador SDO_FILTER es la siguiente:

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

En la sintaxis anterior:

  • geometry1 es una columna de tipo SDO_GEOMETRY en una tabla. Esta columna debe estar indexada espacialmente.

  • geometry2 es un objeto de tipo SDO_GEOMETRY. Este objeto puede o no provenir de una mesa. Si proviene de una tabla, puede o no estar indexada espacialmente.

  • param es una cadena opcional de tipo VARCHAR2. Puede especificar una o ambas palabras clave min_resolution y max_resolution.

Los siguientes ejemplos realizan una operación de filtro primario solamente (sin operación de filtro secundario). Devolverán todas las geometrías mostradas en la Figura 2 que tienen un MBR que interactúa con la ventana de consulta. El resultado de los siguientes ejemplos son geometrías geom_1, geom_2 y geom_3.

Example1 realiza una operación de filtro primario sin insertar la ventana de consulta en una tabla. La ventana se indexará en la memoria y el rendimiento será muy bueno.

Ejemplo 1 Filtro primario con una ventana de consulta temporal

SELECT A.Feature_ID FROM TARGET A  WHERE sdo_filter(A.shape, SDO_geometry(2003,NULL,NULL,
                                       SDO_elem_info_array(1,1003,3),
                                       SDO_ordinate_array(x1,y1, x2,y2))
                           ) = 'TRUE';   

En el Ejemplo 1, (x1, y1) y (x2, y2) son las esquinas inferior izquierda y superior derecha de la ventana de consulta.


1
Genial ... Entonces debería crear la geometría del círculo para representar el radio y luego ver qué polígonos se cruzan ... interesante ... gracias por la información
Luché con un oso una vez.

Sí ... adelante ... Espero que funcione bien para ti.
l.lijith

5

Cualquier intento de incluir A probablemente incluirá D, E, F, G. El problema no puede resolverse sin tener una ruta exacta que defina cada área de código postal.

Encuentre dicha base de datos, luego construya un SPATIALíndice usando tales polígonos arbitrarios.


Sé que necesito datos espaciales (y los tengo, pero está en una tabla de Oracle y no encuentro mucha información sobre cómo convertirlos) ... el problema es descubrir cómo consultar los datos.
Luché con un oso una vez.

Si está satisfecho con el rendimiento del nuevo código, probablemente sea el mejor. Nota: La consulta enumera la distancia a cada zip, por lo que probablemente no haya potencial de optimización. (Estaré gratamente sorprendido si obtienes un mejor código.)
Rick James

eso es algo en lo que estoy pensando también. Te daré la recompensa antes de que se agote el tiempo y obtengas la mitad de todos modos ... solo quiero ver qué otras respuestas podría obtener primero.
Luché con un oso una vez.

3

Lo estás haciendo mal. Primero, si es posible, use PostGIS, que es el RDMBS líder con solución espacial.

Entonces quieres seguir estos pasos.

  1. Despliegue las ZCTA (áreas de tabulación de código postal) del conjunto de datos TIGER del censo . Los códigos postales no se conocen con certeza. Oficialmente, los códigos postales son solo para uso interno de USPS. Debido a que todos los usan, incluido el gobierno, la segunda fuente más autorizada se ha convertido en los archivos de forma ZCTA.
  2. Importe estos archivos de forma a su base de datos, con PostgreSQL puede usar fácilmente shp2pgsql
  3. Indice la geometría que importó.

    CREATE INDEX ON census_zcta USING gist (geog);
    ANALYZE census_zcta;
  4. Ejecute una consulta de Punto de interés (POI) contra los archivos de forma. El punto de interés en su caso son los cables de entrada, esto se verá así,

    SELECT *
    FROM census_zcta AS zcta
      WHERE ST_Intersects( zcta, ST_MakePoint(long,lat)::geog );

ℹ 1609.344 Metros = 1 Milla

MySQL

Con MySQL tendrás

  1. Use ogr2ogr para generar declaraciones de inserción de MySQL para el archivo de forma censal.
  2. Se usa MBRIntersectspara utilizar el índice espacial. La consulta final debe verse como

    SELECT *
    FROM zcta
    WHERE MBRIntersects( geom, Point(long,lat) )
      AND ST_Intersects ( geom, Point(long,lat) );

3
1) Sé que lo estaba haciendo mal. Por eso pregunté. 2) la empresa para la que trabajo tiene acceso pagado a los límites internos del código postal de los usps. trabajamos directamente con usps para este proyecto, y 3) en general, lo que sugiere que OP utiliza un conjunto de herramientas completamente diferente no es una respuesta adecuada.
Luché con un oso una vez.

1
@iwrestledabearonce Puedes hacer todo esto con MySQL 8 también, simplemente sustitúyelo ST_DWithinporMBRIntersects
Evan Carroll

1
"acceso pagado a los límites internos del código postal de los usps" ¿conoce el nombre de ese producto? AFAIK no existe tal cosa. (aunque USPS ofrece 2 productos de datos y algunas API para la dirección de decodificación)
Evan Carroll

1
gracias por agregar la información sobre mysql. +1. la API no es pública y no aparece en ningún sitio web, de hecho, la URL del punto final ni siquiera tiene un nombre de dominio, lo solicitamos directamente desde la dirección IP. sin embargo, solo para demostrar que la API existe, se enumera en este documento (los 3 que se refieren a EDDM son a los que me refiero) usps.com/business/web-tools-apis/archive/…
un oso una vez.

1
En realidad, eso parece legítimo si está logrando el punto final EDDM / SelectZIP. Eso no se anuncia para ese propósito, pero felicitaciones por encontrar ese punto final.
Evan Carroll

1

Consulte este conjunto de datos de GreatData.com (tenga en cuenta que esto no es de código abierto sino un servicio pago).

Utilizan la densidad de población en lugar del centro de la cremallera.

Y cómo usar el tipo de datos espaciales del servidor sql para obtener resultados correctos y rápidos.

Espero que esto ayude.


¿Este conjunto de datos está disponible para MySQL o solo para SQL Server?
ypercubeᵀᴹ
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.