Проблема получения молний в радиусе через MySQL


9

У меня есть таблица почтовых индексов, которая включает в себя центральный лат, lng для каждого почтового индекса. Я использую его, чтобы получить список почтовых индексов в пределах определенного радиуса мили из любой произвольной точки.

Мне просто пришло в голову, что то, что центральная точка молнии не находится в пределах заданного радиуса, не означает, что сам почтовый индекс не находится в пределах радиуса.

Я использовал свои передовые художественные навыки, чтобы проиллюстрировать это:

введите описание изображения здесь

  • Зеленые полосатые пятна представляют почтовые индексы A, B и C.

  • Красные пятна - это географические центры для каждого почтового индекса.

  • Точка фуксии - это целевое местоположение, и ..

  • Кусочек синего круга находится в радиусе 1 мили от цели

Если я выполню запрос для всех почтовых индексов в радиусе 1 мили от розового пятна, будут возвращены только почтовые индексы B и C, поскольку центральная точка для почтового индекса 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

Как, черт возьми, я пишу запрос, который будет включать zip A в результаты?

У меня есть доступ к пространству / геометрии для каждого почтового индекса, который я могу добавить в таблицу, если это необходимо, но я понятия не имею, как бы я использовал его для этой цели в MySQL.


Изменить : я провел день, читая документы Oracle и MySQL для пространственных данных и сумел успешно преобразовать мои пространственные данные в MySQL . Как мне написать подобный запрос, который использует столбец геометрии вместо широты и долготы? Я использую 2D-данные .. геометрия только полигоны и мультиполигоны ..

Я думаю, что я вроде понял это ..

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

Я пока оставлю награду открытой на случай, если у кого-то найдется лучшее и более эффективное решение.

Ответы:


7

Из индексации и запроса пространственных данных в Oracle в Oracle® Spatial Developer Guide 11g Release 2 (11.2):

Запрос пространственных данных

Spatial использует двухуровневую модель запросов с первичными и вторичными фильтрами для разрешения пространственных запросов и пространственных объединений. Термин «двухуровневый» означает, что для разрешения запросов выполняются две разные операции. Если обе операции выполняются, возвращается точный набор результатов.

Вы не можете добавить имя ссылки на базу данных (dblink) к имени пространственной таблицы в запросе, если для этой таблицы определен пространственный индекс.

Пространственный запрос

В пространственном индексе R-дерева каждая геометрия представлена ​​своим минимальным ограничительным прямоугольником (MBR). Рассмотрим следующий слой, содержащий несколько объектов на рисунке 1. Каждый объект помечается своим именем геометрии (geom_1 для строки строки, geom_2 для четырехстороннего многоугольника, geom_3 для треугольного многоугольника и geom_4 для эллипса), а MBR вокруг каждого объекта представляется пунктирной линией.

Рисунок 1 Геометрия с MBR

Описание "Геометрии Figure1 с MBR"

Типичным пространственным запросом является запрос всех объектов, которые находятся в пределах окна запроса, то есть определенного забора или окна. Окно динамического запроса относится к прямоугольной области, которая не определена в базе данных, но должна быть определена до ее использования. На рисунке 2 показана та же геометрия, что и на рисунке 1, но добавлено окно запроса, представленное жирной пунктирной линией.

Слой Figure2 с окном запросов

Описание «слоя Figure2 с окном запросов»

На рисунке 2 окно запроса охватывает части геометрий geom_1 и geom_2, а также часть MBR для geom_3, но не фактическую геометрию geom_3. Окно запроса не охватывает какую-либо часть геометрии geom_4 или ее MBR.

Основной оператор фильтра

Оператор SDO_FILTER реализует основную часть фильтра двухэтапного процесса, включенного в модель обработки запросов Oracle Spatial. Первичный фильтр использует данные индекса для определения только того, может ли взаимодействовать набор пар объектов-кандидатов. В частности, первичный фильтр проверяет, взаимодействуют ли MBR объектов-кандидатов, а не взаимодействуют ли сами объекты. Синтаксис оператора SDO_FILTER выглядит следующим образом:

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

В предыдущем синтаксисе:

  • geometry1 - это столбец типа SDO_GEOMETRY в таблице. Этот столбец должен быть пространственно проиндексирован.

  • geometry2 - это объект типа SDO_GEOMETRY. Этот объект может или не может прийти из таблицы. Если оно исходит из таблицы, оно может или не может быть пространственно проиндексировано.

  • param - необязательная строка типа VARCHAR2. Он может указывать одно или оба ключевых слова min_resolution и max_resolution.

В следующих примерах выполняется только операция первичного фильтра (без операции вторичного фильтра). Они вернут все геометрии, показанные на рисунке 2, которые имеют MBR, который взаимодействует с окном запроса. Результатом следующих примеров являются геометрии geom_1, geom_2 и geom_3.

Example1 выполняет первичную операцию фильтрации без вставки окна запроса в таблицу. Окно будет проиндексировано в памяти, и производительность будет очень хорошей.

Пример 1 Основной фильтр с окном временного запроса

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';   

В примере 1 (x1, y1) и (x2, y2) - левый нижний и верхний правый углы окна запроса.


1
Круто .. Так что я должен создать геометрию круга для представления радиуса, а затем просто посмотреть, какие полигоны пересекаются ... интересно ... спасибо за информацию
я однажды боролся с медведем.

Да .. давай ... Надеюсь, у тебя все хорошо.
l.lijith

5

Любая попытка включить A, вероятно, будет включать D, E, F, G. Проблема не может быть решена без точного пути, определяющего каждую область почтового индекса.

Найдите такую ​​базу данных, затем создайте SPATIALиндекс, используя такие произвольные многоугольники.


Я знаю, что мне нужны пространственные данные (и они у меня есть, но они есть в таблице Oracle, и я не нахожу много информации о том, как их преобразовать) ... проблема состоит в том, чтобы выяснить, как запросить данные.
Я боролся с медведем один раз.

Если вы довольны производительностью нового кода, это, вероятно, лучшее. Примечание. В запросе указывается расстояние до каждого почтового индекса, поэтому вероятность оптимизации отсутствует. (Я буду приятно удивлен, если вы получите лучший код.)
Рик Джеймс

Я тоже так думаю. Я дам тебе награду, пока она не истечет, а ты все равно получишь половину ... просто хочу посмотреть, какие еще ответы я мог бы получить в первую очередь.
Я боролся с медведем один раз.

3

Ты делаешь это неправильно. Во-первых, если возможно, используйте PostGIS - ведущее решение RDMBS с пространственным решением.

Затем вы хотите выполнить следующие шаги.

  1. Потяните вниз ZCTA (области табуляции почтового индекса) из набора данных TIGER переписи . Почтовые индексы на самом деле не знают наверняка. Официально почтовые индексы предназначены только для внутреннего использования USPS. Поскольку их используют все, в том числе и правительство, вторым наиболее авторитетным источником стали шейп-файлы ZCTA.
  2. Импортируйте эти шейп-файлы в вашу базу данных, с PostgreSQL вы можете легко использовать shp2pgsql
  3. Индексируйте геометрию, которую вы импортировали.

    CREATE INDEX ON census_zcta USING gist (geog);
    ANALYZE census_zcta;
    
  4. Выполните запрос точки интереса (POI) для шейп-файлов. В вашем случае интересным является входные шнуры, это будет выглядеть так,

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

09 1609,344 метра = 1 миля

MySQL

С MySQL у вас будет

  1. Используйте ogr2ogr для вывода операторов вставки MySQL для шейп-файла переписи.
  2. Используйте MBRIntersectsдля использования пространственного индекса. Конечный запрос должен выглядеть примерно так

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

3
1) я знаю, что делал неправильно. вот почему я спросил. 2) компания, в которой я работаю, имеет платный доступ к внутренним границам почтового индекса usps. мы работали непосредственно с usps для этого проекта, и 3) в целом, предполагая, что OP использует совершенно другой набор инструментов, это неправильный ответ.
Я боролся с медведем один раз.

1
@iwrestledabearonce Вы можете сделать все эти вещи с MySQL-слишком просто подставить ST_DWithinсMBRIntersects
Evan Carroll

1
"платный доступ к внутренним границам почтового индекса usps" , вы случайно не знаете название этого продукта? AFAIK нет такой вещи. (хотя USPS действительно предлагает 2 продукта данных и некоторые API для декодирования адреса)
Эван Кэрролл

1
Спасибо за добавление информации о MySQL. +1. API-интерфейс не является общедоступным, и он не указан ни на одном веб-сайте, фактически URL-адрес конечной точки даже не имеет доменного имени, мы запрашиваем его непосредственно с IP-адреса. однако, просто чтобы доказать, что API существует, он указан в этом документе (3, которые относятся к EDDM - это те, на которые я ссылаюсь
Я боролся с медведем один раз.

1
Это действительно кажется правомерным, если вы используете конечную точку EDDM / SelectZIP. Это не рекламируется для этой цели, но слава к поиску этой конечной точки.
Эван Кэрролл

1

Проверьте этот набор данных от GreatData.com (обратите внимание, что это не открытый исходный код, а платный сервис).

Они используют плотность населения вместо центра молнии.

И как использовать SQL Server пространственный тип данных для быстрого получения правильных результатов.

Надеюсь это поможет.


Этот набор данных доступен для MySQL или только для SQL Server?
ypercubeᵀᴹ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.