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.

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.


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.


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

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.


Czy ten zestaw danych jest dostępny dla MySQL, czy tylko dla SQL Server?
— ypercubeᵀᴹ
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.