Проблема з отримання блискавок в радіусі через MySQL


9

У мене є таблиця поштових індексів, яка включає центр lat, 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 . Як мені почати писати подібний запит, який використовує стовпчик геометрії замість lat та long? Я використовую 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® 11г, випуск 2 (11.2):

Запит просторових даних

Простір використовує дворівневу модель запитів з первинними та вторинними операціями фільтрації для вирішення просторових запитів та просторових з'єднань. Термін дворівневий означає, що для вирішення запитів виконуються дві різні операції. Якщо обидві операції виконуються, точний набір результатів повертається.

Ви не можете додати ім'я просторової таблиці до запиту імені посилання бази даних (dblink), якщо в цій таблиці визначений просторовий індекс.

Просторовий запит

У просторовому індексі R-дерева кожна геометрія представлена ​​своїм мінімальним обмежуючим прямокутником (MBR). Розглянемо наступний шар, що містить кілька об’єктів на рисунку1. Кожен об’єкт позначений назвою геометрії (geom_1 для рядкової лінії, geom_2 для чотиристороннього багатокутника, geom_3 для трикутного багатокутника і geom_4 для еліпса), а MBR навколо кожного об'єкта представлено пунктирною лінією.

Рисунок1 Геометрії з MBR

Опис "Рисунок1 Геометрії з MBR"

Типовий просторовий запит - це запитувати всі об'єкти, що лежать у вікні запиту, тобто визначеному паркані чи вікні. Динамічне вікно запитів посилається на прямокутну область, яка не визначена в базі даних, але вона повинна бути визначена перед її використанням. На рисунку2 показані ті ж геометрії, що і на рисунку1, але додається вікно запитів, представлене важким полем з пунктирними рядками

Рисунок2 Шар із вікном запиту

Опис "Шару рисунка2 із вікном запиту"

На малюнку 2 вікно запиту охоплює частини геометрії geom_1 та geom_2, а також частину MBR для geom_3, але жодної фактичної геометрії geom_3. Вікно запиту не охоплює жодної частини геометрії geom_4 або її MBR.

Оператор первинного фільтра

Оператор SDO_FILTER реалізує первинну частину фільтру двоступеневого процесу, що бере участь у моделі обробки просторових запитів Oracle. Первинний фільтр використовує дані індексу для визначення лише того, якщо набір пар кандидатних об'єктів може взаємодіяти. Зокрема, первинний фільтр перевіряє, чи взаємодіють 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 виконує первинну операцію фільтра без вставлення вікна запиту в таблицю. Вікно буде індексовано в пам’яті і продуктивність буде дуже хорошою.

Example1 Первинний фільтр із тимчасовим вікном запитів

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
Круто .. Тож я повинен створити геометрію кола, щоб представити радіус, а потім просто побачити, які багатокутники перетинаються .. цікаво .. thx для інформації
я боровся ведмедям один раз.

Так ... надіюсь, сподіваюся, що це добре працює для вас.
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 );

ℹ 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) загалом, припускаючи, що ОП використовує зовсім інший набір інструментів, не є правильною відповіддю.
Я боровся ведмедя одного разу.

1
@iwrestledabearonce Ви можете зробити всі ці речі з MySQL-занадто просто підставити ST_DWithinзMBRIntersects
Evan Carroll

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

1
дякую за додавання інформації про mysql. +1. api не є загальнодоступним і не вказаний на будь-якому веб-сайті, адже URL-адреса кінцевої точки навіть не має доменного імені, ми вимагаємо його безпосередньо з ip-адреси. однак, щоб довести існування api, він вказаний у цьому документі (3, які посилаються на EDDM - це ті, про які я звертаюся) usps.com/business/web-tools-apis/archive/…
я боровся з ведмедем один раз.

1
Це насправді здається законним, якщо ви знімаєте кінцеву точку EDDM / SelectZIP. Це не рекламується для цієї мети, але кудо шукає цю кінцеву точку.
Еван Керролл

1

Перегляньте цей набір даних з GreatData.com (зауважте, що це не відкритий код, а платна послуга).

Вони використовують щільність населення замість центру блискавки.

І як використовувати тип просторових даних сервера sql для отримання швидких правильних результатів.

Сподіваюсь, це допомагає.


Чи доступний цей набір даних для MySQL чи це лише для SQL Server?
ypercubeᵀᴹ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.