Problem z uzyskiwaniem zamków w promieniu przez MySQL

9

Mam tabelę kodów pocztowych, która zawiera środkową długość, długość każdego kodu pocztowego. Używam go, aby uzyskać listę kodów pocztowych w promieniu mili z dowolnego dowolnego punktu.

Właśnie przyszło mi do głowy, że to, że punkt środkowy zamka nie znajduje się w danym promieniu, nie oznacza, że ​​sam zamek nie mieści się w promieniu.

Użyłem moich super zaawansowanych umiejętności plastycznych, aby zilustrować tę kwestię:

wprowadź opis zdjęcia tutaj

  • Zielone paski BLOB reprezentują kody pocztowe A, B i C.

  • Czerwone smugi są geograficznymi centrami każdego kodu pocztowego

  • Kropka fuksji to miejsce docelowe i ..

  • Nierówny niebieski okrąg znajduje się w promieniu 1 mili od miejsca docelowego

Jeśli uruchomię zapytanie dla wszystkich kodów pocztowych w promieniu 1 mili od różowej plamy, tylko kody pocztowe B i C zostaną zwrócone, ponieważ punkt środkowy dla suwaka A nie znajduje się w promieniu jednej mili, mimo że różowa plama sama jest wyraźnie w kodzie pocztowym 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

Jak do cholery mam napisać zapytanie, które będzie zawierać zip A w wynikach?

Mam dostęp do danych przestrzennych / geometrycznych dla każdego kodu pocztowego, który mogę dodać do tabeli, jeśli zajdzie taka potrzeba, ale nie mam pojęcia, jak mógłbym go użyć w tym celu w MySQL.


Edycja : spędziłem dzień czytając dokumenty Oracle i MySQL dla danych przestrzennych i udało mi się pomyślnie przekonwertować moje dane przestrzenne na MySQL . Jak przejść do pisania podobnego zapytania, które używa kolumny geometrii zamiast szerokości i długości? Używam danych 2D .. geometria to tylko wielokąty i multipoligony ..

Myślę, że to wymyśliłem ...

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

Zostawię nagrodę na razie otwartą na wypadek, gdyby ktoś miał lepsze, bardziej wydajne rozwiązanie.

Raz siłowałem się z niedźwiedziem.
źródło

Odpowiedzi:

7

Z indeksowania i wyszukiwania danych przestrzennych w Oracle w Oracle Spatial Developer's Guide 11g Release 2 (11.2):

Zapytanie o dane przestrzenne

Spatial wykorzystuje dwuwarstwowy model zapytań z podstawowymi i wtórnymi operacjami filtrowania do rozwiązywania zapytań przestrzennych i sprzężeń przestrzennych. Termin dwuwarstwowy oznacza, że ​​wykonywane są dwie różne operacje w celu rozwiązania zapytań. Jeśli zostaną wykonane obie operacje, zwracany jest dokładny zestaw wyników.

Nie można dołączyć nazwy łącza bazy danych (dblink) do nazwy tabeli przestrzennej w zapytaniu, jeśli indeks przestrzenny jest zdefiniowany w tej tabeli.

Zapytanie przestrzenne

W przestrzennym indeksie drzewa R każda geometria jest reprezentowana przez minimalny prostokąt ograniczający (MBR). Rozważ następującą warstwę zawierającą kilka obiektów na rysunku 1. Każdy obiekt jest oznaczony nazwą geometrii (geom_1 dla ciągu linii, geom_2 dla czworoboku, geom_3 dla trójkąta i geom_4 dla elipsy), a MBR wokół każdego obiektu jest reprezentowany linią przerywaną.

Rysunek 1 Geometria z MBR

Opis „Figur 1 Geometrii z MBR”

Typowym zapytaniem przestrzennym jest żądanie wszystkich obiektów znajdujących się w oknie zapytania, to znaczy zdefiniowanym ogrodzeniu lub oknie. Dynamiczne okno zapytania odnosi się do prostokątnego obszaru, który nie jest zdefiniowany w bazie danych, ale musi zostać zdefiniowany przed użyciem. Rysunek 2 pokazuje te same geometrie jak na rysunku 1, ale dodaje okno zapytania reprezentowane przez ciężkie pole z linią przerywaną.

Rysunek 2 Warstwa z oknem zapytania

Opis „Warstwa Figure2 z oknem zapytania”

Na rysunku 2 okno zapytania obejmuje części geometrii geom_1 i geom_2, a także część MBR dla geom_3, ale żadnej z faktycznej geometrii geom_3. Okno zapytania nie obejmuje żadnej części geometrii geom_4 ani jej MBR.

Główny operator filtra

Operator SDO_FILTER implementuje część filtru podstawowego dwuetapowego procesu zaangażowanego w model przetwarzania zapytań Oracle Spatial. Filtr główny korzysta z danych indeksu w celu ustalenia, czy zestaw kandydujących par obiektów może oddziaływać. W szczególności filtr główny sprawdza, czy MBR obiektów kandydujących oddziałują, a nie czy same obiekty oddziałują. Składnia operatora SDO_FILTER jest następująca:

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

W poprzedniej składni:

  • geometry1 to kolumna typu SDO_GEOMETRY w tabeli. Ta kolumna musi być indeksowana przestrzennie.

  • geometry2 jest obiektem typu SDO_GEOMETRY. Ten obiekt może, ale nie musi pochodzić ze stołu. Jeśli pochodzi z tabeli, może być indeksowany przestrzennie lub nie.

  • parametr jest opcjonalnym ciągiem typu VARCHAR2. Może określać jedno lub oba słowa kluczowe min_resolution i max_resolution.

Poniższe przykłady wykonują tylko operację filtra podstawowego (bez operacji filtra wtórnego). Zwrócą wszystkie geometrie pokazane na rysunku 2, które mają MBR współdziałający z oknem zapytania. Wynikiem poniższych przykładów są geometrie geom_1, geom_2 i geom_3.

Przykład 1 wykonuje podstawową operację filtrowania bez wstawiania okna zapytania do tabeli. Okno zostanie zindeksowane w pamięci, a wydajność będzie bardzo dobra.

Przykład 1 Filtr główny z oknem tymczasowego zapytania

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

W przykładzie 1, (x1, y1) i (x2, y2) są lewym dolnym i prawym górnym rogiem okna zapytania.

l.lijith
źródło
1
Fajnie .. Więc powinienem stworzyć geometrię koła, która będzie reprezentować promień, a następnie po prostu zobacz, które wielokąty przecinają się ... ciekawe .. dzięki za informację
raz walczyłem z niedźwiedziem.
Tak .. dalej ... Mam nadzieję, że to działa dobrze dla ciebie.
l.lijith
5

Każda próba włączenia A będzie prawdopodobnie obejmować D, E, F, G. Problemu nie da się rozwiązać bez dokładnej ścieżki określającej każdy obszar kodu pocztowego.

Znajdź taką bazę danych, a następnie zbuduj SPATIALindeks przy użyciu takich dowolnych wielokątów.

Rick James
źródło
Wiem, że potrzebuję danych przestrzennych (i mam je, ale są one w tabeli Oracle i nie znajduję zbyt wielu informacji o tym, jak je przekonwertować). Problem polega na tym, jak znaleźć dane.
Raz walczyłem z niedźwiedziem.
Jeśli jesteś zadowolony z wydajności nowego kodu, to prawdopodobnie najlepsza. Uwaga: zapytanie podaje odległość do każdego pliku zip, więc prawdopodobnie nie ma możliwości optymalizacji. (Będę mile zaskoczony, jeśli dostaniesz lepszy kod.)
Rick James
o tym też myślę. Dam ci nagrodę, zanim upłynie limit czasu, a dostaniesz jej połowę. Po prostu chcę zobaczyć, jakie inne odpowiedzi mogę uzyskać jako pierwsze.
Raz walczyłem z niedźwiedziem.
3

Robisz to źle. Najpierw, jeśli to możliwe, użyj PostGIS - który jest wiodącym RDMBS z rozwiązaniem przestrzennym.

Następnie chcesz wykonać następujące kroki.

  1. Pociągnij w dół ZCTA (Zip Code tabelaryczne obszarów) ze spisu powszechnego za TIGER zbiorze . Kody pocztowe nie są tak naprawdę pewne. Oficjalnie kody pocztowe są przeznaczone wyłącznie do użytku wewnętrznego przez USPS. Ponieważ wszyscy ich używają, w tym rząd, drugim najbardziej wiarygodnym źródłem stały się pliki kształtów ZCTA.
  2. Zaimportuj te pliki kształtów do swojej bazy danych, korzystając z PostgreSQL, z którego możesz łatwo korzystać shp2pgsql
  3. Indeksuj zaimportowaną geometrię.

    CREATE INDEX ON census_zcta USING gist (geog);
    ANALYZE census_zcta;
  4. Uruchom zapytanie o punkt zainteresowania (POI) przeciwko plikom kształtów. Punktem zainteresowania w twoim przypadku są przewody wejściowe, będzie to wyglądać tak,

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

ℹ 1609.344 Metry = 1 Mila

MySQL

Z MySQL będziesz mieć

  1. Użyj ogr2ogr, aby wyświetlić instrukcje wstawiania MySQL dla pliku kształtu spisu.
  2. Użyj, MBRIntersectsaby wykorzystać indeks przestrzenny. Końcowe zapytanie powinno wyglądać mniej więcej tak

    SELECT *
    FROM zcta
    WHERE MBRIntersects( geom, Point(long,lat) )
      AND ST_Intersects ( geom, Point(long,lat) );
Evan Carroll
źródło
3
1) wiem, że źle to zrobiłem. dlatego zapytałem. 2) firma, dla której pracuję, ma płatny dostęp do wewnętrznych granic kodu pocztowego usp. pracowaliśmy bezpośrednio z usps dla tego projektu i 3) ogólnie, sugerując, że OP używa zupełnie innego zestawu narzędzi, nie jest właściwą odpowiedzią.
Raz walczyłem z niedźwiedziem.
1
@iwrestledabearonce można zrobić wszystkie te rzeczy z MySQL 8 też po prostu wymienia na ST_DWithinzMBRIntersects
Evan Carroll
1
„płatny dostęp do wewnętrznych granic kodu pocztowego usps”. Czy znasz nazwę tego produktu? AFAIK nie ma czegoś takiego. (chociaż USPS oferuje 2 produkty danych i niektóre interfejsy API do dekodowania adresu)
Evan Carroll
1
dziękuję za dodanie informacji o mysql. +1. interfejs API nie jest publiczny i nie jest wymieniony na żadnej stronie, w rzeczywistości adres URL punktu końcowego nie ma nawet nazwy domeny, prosimy o to bezpośrednio z adresu IP. jednakże, aby udowodnić, że interfejs API istnieje, jest wymieniony w tym dokumencie (3, które odnoszą się do EDDM, to te, o których mówię) usps.com/business/web-tools-apis/archive/…
walczyłem z niedźwiedziem pewnego razu.
1
W rzeczywistości wydaje się to uzasadnione, jeśli pobierasz punkt końcowy EDDM / SelectZIP. Nie jest to reklamowane w tym celu, ale uznanie dla znalezienia tego punktu końcowego.
Evan Carroll
1

Sprawdź ten zestaw danych z GreatData.com (pamiętaj, że nie jest to oprogramowanie typu open source, ale usługa płatna).

Używają gęstości zaludnienia zamiast środka zamka błyskawicznego.

I jak używać typu danych przestrzennych serwera SQL, aby uzyskać szybkie prawidłowe wyniki.

Mam nadzieję że to pomoże.

Matt McDonald
źródło
Czy ten zestaw danych jest dostępny dla MySQL, czy tylko dla SQL Server?
ypercubeᵀᴹ