Wenn ich eine Frage habe, die Cafés in der Nähe zurückgibt:
SELECT * FROM cafes c WHERE (
ST_DWithin(
ST_GeographyFromText(
'SRID=4326;POINT(' || c.longitude || ' ' || c.latitude || ')'
),
ST_GeographyFromText('SRID=4326;POINT(-76.000000 39.000000)'),
2000
)
)
Wie wähle ich die Entfernung aus und ordne sie auch nach Entfernung?
Gibt es einen effizienteren Weg als diesen:
SELECT id,
ST_Distance(ST_GeographyFromText('SRID=4326;POINT(-76.000000 39.000000)'),
ST_GeographyFromText(
'SRID=4326;POINT(' || c.longitude || ' ' || c.latitude || ')')
) as distance
FROM cafes c
WHERE (
ST_DWithin(
ST_GeographyFromText(
'SRID=4326;POINT(' || c.longitude || ' ' || c.latitude || ')'
),
ST_GeographyFromText('SRID=4326;POINT(-76.000000 39.000000)'),
2000
)
) order by distance
postgresql
postgresql-9.2
postgis
gist-index
Gandalf StormCrow
quelle
quelle
WHERE
Klausel verwenden? Möchten Sie es mit einer Schwelle vergleichen?Antworten:
Erstens , die Verwendung
anstatt
Pro Dokumentation:
Als nächstes wird die Abfrage kürzer zu machen und geben Sie nur Parameter suchen einmal (ohne viel Einfluss auf die Leistung), verwenden Sie eine Unterabfrage (oder CTE):
Schließlich benötigen Sie einen GiST-Index , um dies für große Tabellen schnell zu machen. Per Dokumentation zu
ST_DWithin()
:Sie könnten dies mit einem Funktionsindex für den Ausdruck am Anfang der Antwort arbeiten lassen. Aber ich würde zunächst eine Typenspalte speichern
geography
(nennen wir esthegeog
) und einen einfachen GiST-Index wie folgt erstellen:Zu dieser viel einfacheren und schnelleren Abfrage gelangen:
Aktualisiert, um
geography
mitgeography
übereinzustimmen, wie von @ LR1234567 im Kommentar hervorgehoben. Alternativ können Sie mit arbeitengeometry
. Alle hier verwendeten Funktionen funktionieren für beide (außer fürST_MakePoint
die angehängte Besetzung). Was ist der Unterschied?Wenn Sie die n nächstgelegenen Cafés stattdessen alle innerhalb eines Radius erhalten möchten , ziehen Sie eine Suche nach dem nächsten Nachbarn in Betracht . Oft bequemer.
quelle
UPDATE cafes SET thegeog = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326);
Muss ich den Teil noch verwenden, inselect ST_GeographyFromText .... AS t(x)
dem ich diese Spalte jetzt ausgefüllt habe? Kann ich diese Spalte nutzen und in der Nähe direkt danach fragen, anstatt lat / long anzugeben?