Ana içeriğe geç
Kesit SQL
İleri · Modern SQL

Coğrafi veri: mesafe, en yakın nokta ve uzamsal tipler

Haversine ile mesafe, PostGIS, SQL Server geography, BigQuery GEOGRAPHY.

Uygulamada aç, 5 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Konum sorguları

“Müşteriye en yakın mağaza”, “5 km içindeki kuryeler”, “hangi ilçede?” gibi sorular coğrafi (uzamsal) veri gerektirir. Basit mesafe hesabı düz SQL ile yapılabilir; ciddi işler için uzamsal tipler ve indeksler kullanılır.

Haversine: iki koordinat arasındaki mesafe

Dünyayı küre kabul ederek iki enlem/boylam arasındaki büyük daire mesafesi (km):

WITH sehir AS (
  SELECT 'İstanbul' AS ad, 41.0082 AS enlem, 28.9784 AS boylam UNION ALL
  SELECT 'Ankara',   39.9334, 32.8597 UNION ALL
  SELECT 'İzmir',    38.4237, 27.1428 UNION ALL
  SELECT 'Bursa',    40.1885, 29.0610 UNION ALL
  SELECT 'Antalya',  36.8969, 30.7133
)
SELECT a.ad AS nereden, b.ad AS nereye,
       ROUND(6371 * 2 * ASIN(SQRT(
         POWER(SIN((b.enlem - a.enlem) * 0.0174532925 / 2), 2) +
         COS(a.enlem * 0.0174532925) * COS(b.enlem * 0.0174532925) *
         POWER(SIN((b.boylam - a.boylam) * 0.0174532925 / 2), 2))), 0) AS km
FROM sehir a JOIN sehir b ON a.ad = 'İstanbul' AND b.ad <> a.ad
ORDER BY km;

(0.0174532925 = π/180, dereceyi radyana çevirir; 6371 km Dünya'nın ortalama yarıçapı.)

Uzamsal tipler

-- PostgreSQL + PostGIS
CREATE EXTENSION postgis;
ALTER TABLE magaza ADD COLUMN konum geography(Point, 4326);
UPDATE magaza SET konum = ST_SetSRID(ST_MakePoint(boylam, enlem), 4326)::geography;
CREATE INDEX ix_magaza_konum ON magaza USING GIST (konum);

-- 5 km içindeki mağazalar ve en yakın 3
SELECT ad, ST_Distance(konum, ST_MakePoint(28.98, 41.01)::geography) / 1000 AS km
FROM magaza
WHERE ST_DWithin(konum, ST_MakePoint(28.98, 41.01)::geography, 5000)
ORDER BY konum <-> ST_MakePoint(28.98, 41.01)::geography
LIMIT 3;

-- SQL Server
DECLARE @ben geography = geography::Point(41.01, 28.98, 4326);
SELECT TOP (3) ad, konum.STDistance(@ben) / 1000 AS km FROM dbo.magaza ORDER BY konum.STDistance(@ben);

-- BigQuery
SELECT ad, ST_DISTANCE(konum, ST_GEOGPOINT(28.98, 41.01)) / 1000 AS km
FROM anadolu.magaza
WHERE ST_DWITHIN(konum, ST_GEOGPOINT(28.98, 41.01), 5000);

-- MySQL 8
SELECT ad, ST_Distance_Sphere(konum, POINT(28.98, 41.01)) / 1000 AS km FROM magaza;
Sıra tuzağıFonksiyonların çoğu nokta için (boylam, enlem) sırası ister (x, y); SQL Server'ın geography::Point fonksiyonu ise (enlem, boylam). Ters yazılan koordinatlar okyanusun ortasında nokta üretir.

SRID 4326 = WGS 84 (GPS koordinatları). geography mesafeyi metre olarak küre üzerinde, geometry düzlemde hesaplar.

Alıştırmalara geç (5)