Problem beim Abrufen von Reißverschlüssen im Radius über MySQL


9

Ich habe eine Tabelle mit Postleitzahlen, die die mittlere Lat-Länge für jede Postleitzahl enthält. Ich benutze es, um eine Liste von Postleitzahlen innerhalb eines bestimmten Meilenradius von einem beliebigen Punkt zu erhalten.

Mir ist gerade eingefallen, dass nur weil der Mittelpunkt eines Reißverschlusses nicht innerhalb eines bestimmten Radius liegt, dies nicht bedeutet, dass der Reißverschluss selbst nicht innerhalb des Radius liegt.

Ich habe meine hochentwickelten Kunstfähigkeiten genutzt, um den Punkt hier zu veranschaulichen:

Geben Sie hier die Bildbeschreibung ein

  • Die grün gestreiften Blobs repräsentieren die Postleitzahlen A, B und C.

  • Die roten Flecken sind die geografischen Zentren für jede Postleitzahl

  • Der Fuchsia-Punkt ist der Zielort und ..

  • Der klumpige blaue Kreis ist einen Radius von 1 Meile vom Zielort entfernt

Wenn ich eine Abfrage für alle Postleitzahlen innerhalb eines Radius von 1 Meile vom rosa Fleck ausführe, werden nur die Postleitzahlen B und C zurückgegeben, da der Mittelpunkt für Postleitzahl A nicht innerhalb des Radius von einer Meile liegt, obwohl der rosa Fleck selbst liegt ist eindeutig in Postleitzahl 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

Wie zum Teufel schreibe ich eine Abfrage, die Zip A in die Ergebnisse einbezieht?

Ich habe Zugriff auf Raum / Geometrie für jede Postleitzahl, die ich bei Bedarf zur Tabelle hinzufügen kann, aber ich habe keine Ahnung, wie ich sie für diesen Zweck in MySQL verwenden würde.


Bearbeiten : Ich habe einen Tag lang die Oracle- und MySQL-Dokumente für räumliche Daten gelesen und es geschafft , meine räumlichen Daten erfolgreich in MySQL zu konvertieren . Wie schreibe ich eine ähnliche Abfrage, bei der die Geometriespalte anstelle von lat und long verwendet wird? Ich verwende 2D-Daten. Die Geometrie besteht nur aus Polygonen und Multipolygonen.

Ich glaube, ich habe es irgendwie herausgefunden.

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

Ich werde das Kopfgeld vorerst offen lassen, falls jemand eine bessere, effizientere Lösung hat.

Antworten:


7

Von Indizierung und Abfragen von Geodaten in Oracle in dem Oracle® Spatial - Entwicklerhandbuch 11g Release 2 (11.2):

Geodaten abfragen

Spatial verwendet ein zweistufiges Abfragemodell mit primären und sekundären Filteroperationen, um räumliche Abfragen und räumliche Verknüpfungen aufzulösen. Der Begriff zweistufig gibt an, dass zwei unterschiedliche Vorgänge ausgeführt werden, um Abfragen aufzulösen. Wenn beide Operationen ausgeführt werden, wird die genaue Ergebnismenge zurückgegeben.

Sie können einen Datenbanklinknamen (dblink) nicht an den Namen einer räumlichen Tabelle in einer Abfrage anhängen, wenn für diese Tabelle ein räumlicher Index definiert ist.

Raumabfrage

In einem räumlichen R-Baum-Index wird jede Geometrie durch ihr minimales Begrenzungsrechteck (MBR) dargestellt. Betrachten Sie die folgende Ebene mit mehreren Objekten in Abbildung 1. Jedes Objekt ist mit seinem Geometrienamen gekennzeichnet (geom_1 für die Linienzeichenfolge, geom_2 für das vierseitige Polygon, geom_3 für das dreieckige Polygon und geom_4 für die Ellipse), und der MBR um jedes Objekt wird durch eine gestrichelte Linie dargestellt.

Abbildung 1 Geometrien mit MBRs

Beschreibung von "Abbildung 1 Geometrien mit MBRs"

Eine typische räumliche Abfrage besteht darin, alle Objekte anzufordern, die in einem Abfragefenster liegen, dh einen definierten Zaun oder ein definiertes Fenster. Ein dynamisches Abfragefenster bezieht sich auf einen rechteckigen Bereich, der nicht in der Datenbank definiert ist, der jedoch definiert werden muss, bevor er verwendet wird. Abbildung 2 zeigt die gleichen Geometrien wie in Abbildung 1, fügt jedoch ein Abfragefenster hinzu, das durch das Feld mit der dicken gepunkteten Linie dargestellt wird.

Abbildung 2 Ebene mit einem Abfragefenster

Beschreibung von "Abbildung 2 Ebene mit einem Abfragefenster"

In Abbildung 2 umfasst das Abfragefenster Teile der Geometrien geom_1 und geom_2 sowie einen Teil des MBR für geom_3, jedoch keine der tatsächlichen Geom_3-Geometrien. Das Abfragefenster deckt keinen Teil der Geom_4-Geometrie oder ihres MBR ab.

Primärer Filteroperator

Der Operator SDO_FILTER implementiert den primären Filterteil des zweistufigen Prozesses, der am Oracle Spatial-Abfrageverarbeitungsmodell beteiligt ist. Der Primärfilter verwendet die Indexdaten, um nur zu bestimmen, ob eine Reihe von Kandidatenobjektpaaren interagieren kann. Insbesondere prüft der Primärfilter, ob die MBRs der Kandidatenobjekte interagieren und nicht, ob die Objekte selbst interagieren. Die Syntax des Operators SDO_FILTER lautet wie folgt:

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

In der vorhergehenden Syntax:

  • Geometrie1 ist eine Spalte vom Typ SDO_GEOMETRY in einer Tabelle. Diese Spalte muss räumlich indiziert sein.

  • Geometrie2 ist ein Objekt vom Typ SDO_GEOMETRY. Dieses Objekt kann aus einer Tabelle stammen oder nicht. Wenn es aus einer Tabelle stammt, kann es räumlich indiziert sein oder nicht.

  • param ist eine optionale Zeichenfolge vom Typ VARCHAR2. Es kann eines oder beide der Schlüsselwörter min_resolution und max_resolution angeben.

In den folgenden Beispielen wird nur eine Primärfilteroperation ausgeführt (ohne Sekundärfilteroperation). Sie geben alle in Abbildung 2 gezeigten Geometrien mit einem MBR zurück, der mit dem Abfragefenster interagiert. Das Ergebnis der folgenden Beispiele sind die Geometrien geom_1, geom_2 und geom_3.

Beispiel 1 führt eine primäre Filteroperation aus, ohne das Abfragefenster in eine Tabelle einzufügen. Das Fenster wird im Speicher indiziert und die Leistung ist sehr gut.

Beispiel 1 Primärfilter mit einem temporären Abfragefenster

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

In Beispiel 1 sind (x1, y1) und (x2, y2) die unteren linken und oberen rechten Ecken des Abfragefensters.


1
Cool .. Also sollte ich die Kreisgeometrie erstellen, um den Radius darzustellen und dann einfach sehen, welche Polygone sich schneiden .. interessant .. Danke für die Info
ich habe einmal mit einem Bären gerungen.

Ja ... mach weiter ... Hoffe, es funktioniert gut für dich.
l.lijith

5

Jeder Versuch, A einzuschließen, wird wahrscheinlich D, E, F, G einschließen. Das Problem kann nicht gelöst werden, ohne einen genauen Pfad zu haben, der jeden Postleitzahlbereich definiert.

Suchen Sie eine solche Datenbank und erstellen Sie dann einen SPATIALIndex mit solchen beliebigen Polygonen.


Ich weiß, dass ich räumliche Daten benötige (und ich habe sie, aber sie befinden sich in einer Oracle-Tabelle und ich finde nicht viele Informationen zum Konvertieren). Das Problem besteht darin, herauszufinden, wie die Daten abgefragt werden.
Ich habe einmal mit einem Bären gerungen.

Wenn Sie mit der Leistung des neuen Codes zufrieden sind, ist dies wahrscheinlich die beste. Hinweis: In der Abfrage wird die Entfernung zu jeder Postleitzahl aufgeführt, sodass wahrscheinlich kein Optimierungspotenzial besteht. (Ich werde angenehm überrascht sein, wenn Sie besseren Code erhalten.)
Rick James

Das denke ich auch. Ich gebe dir das Kopfgeld, bevor es abläuft und du trotzdem die Hälfte davon bekommst. Ich will nur sehen, welche anderen Antworten ich zuerst bekomme.
Ich habe einmal mit einem Bären gerungen.

3

Du machst es falsch. Verwenden Sie nach Möglichkeit zunächst PostGIS - das führende RDMBS mit Spatial-Lösung.

Dann möchten Sie diese Schritte ausführen.

  1. Ziehen Sie die ZCTA (Postleitzahl-Tabellierungsbereiche) aus dem TIGER-Datensatz der Volkszählung herunter . Postleitzahlen sind eigentlich nicht sicher bekannt. Offiziell sind Postleitzahlen nur für den internen Gebrauch durch den USPS bestimmt. Da sie von allen verwendet werden, einschließlich der Regierung, sind die ZCTA-Shapefiles die zweitwichtigste Quelle.
  2. Importieren Sie diese Shapefiles in Ihre Datenbank. Mit PostgreSQL können Sie diese problemlos verwenden shp2pgsql
  3. Indizieren Sie die importierte Geometrie.

    CREATE INDEX ON census_zcta USING gist (geog);
    ANALYZE census_zcta;
  4. Führen Sie eine POI-Abfrage (Point-of-Interest) für die Shapefiles aus. Der Punkt von Interesse in Ihrem Fall sind die Eingangskabel, dies wird so aussehen,

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

9. 1609,344 Meter = 1 Meile

MySQL

Mit MySQL haben Sie

  1. Verwenden Sie ogr2ogr, um MySQL-Einfügeanweisungen für das Census Shapefile auszugeben.
  2. Verwenden Sie MBRIntersectsdiese Option, um den räumlichen Index zu verwenden. Die Abfrage beenden sollte ungefähr so ​​aussehen

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

3
1) Ich weiß, dass ich es falsch gemacht habe. deshalb habe ich gefragt. 2) Das Unternehmen, für das ich arbeite, hat den Zugriff auf die internen Postleitzahlgrenzen des USP bezahlt. Wir haben für dieses Projekt direkt mit usps zusammengearbeitet, und 3) im Allgemeinen ist es keine richtige Antwort, dass OP ein völlig anderes Toolset verwendet.
Ich habe einmal mit einem Bären gerungen.

1
@iwrestledabearonce Sie können all diese Sachen mit MySQL 8 auch tun, ersetzen Sie einfach das ST_DWithinmitMBRIntersects
Evan Carroll

1
"Bezahlter Zugriff auf USPS-interne Postleitzahlgrenzen" Kennen Sie zufällig den Namen dieses Produkts? AFAIK gibt es so etwas nicht. (obwohl USPS 2 Datenprodukte und einige APIs zum Decodieren von Adressen anbietet)
Evan Carroll

1
Vielen Dank für das Hinzufügen der Informationen über MySQL. +1. Die API ist nicht öffentlich und auf keiner Website aufgeführt. Tatsächlich hat die Endpunkt-URL nicht einmal einen Domainnamen. Wir fordern sie direkt von der IP-Adresse an. Nur um zu beweisen, dass die API existiert, ist sie in diesem Dokument aufgeführt (die 3, die sich auf EDDM beziehen, sind diejenigen, auf die ich mich beziehe) usps.com/business/web-tools-apis/archive/…
Ich habe mit einem Bären gerungen Einmal.

1
Das scheint tatsächlich legitim zu sein, wenn Sie den EDDM / SelectZIP-Endpunkt abrufen. Das wird nicht für diesen Zweck beworben, aber ein großes Lob, um diesen Endpunkt zu finden.
Evan Carroll

1

Schauen Sie sich diesen Datensatz von GreatData.com an (beachten Sie, dass dies kein Open Source, sondern ein kostenpflichtiger Dienst ist).

Sie verwenden die Bevölkerungsdichte anstelle des Zentrums der Postleitzahl.

Und wie man den räumlichen Datentyp von SQL Server verwendet, um schnell korrekte Ergebnisse zu erhalten.

Hoffe das hilft.


Ist dieser Datensatz für MySQL verfügbar oder nur für SQL Server?
Ypercubeᵀᴹ
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.