ST_Distance() în MySQL

Returnează distanța minimă dintre două geometrii; pentru SRID 4326, în metri, calculată pe elipsoidul Pământului.

Sintaxă
ST_Distance(g1, g2 [, unitate])

Ce face ST_Distance()

Pentru SRID 0, distanța este cea din plan (Pitagora), în unitățile coordonatelor. Pentru un SRID geografic, ca 4326, distanța este geodezică: cea mai scurtă distanță pe elipsoidul WGS 84, în metri. Din MySQL 8.0.18 funcționează pe SRID geografic pentru orice tipuri de geometrii.

Pentru linii și poligoane se returnează cea mai mică distanță dintre ele (0 dacă se ating). Al treilea argument (din MySQL 8.0.14) cere altă unitate, de exemplu 'kilometre'; nu se poate folosi cu SRID 0.

Parametri

Parametru Descriere
g1, g2 Geometriile, cu același SRID.
unitate Opțional: unitatea rezultatului ('metre', 'kilometre', 'foot' etc.).

Ce returnează

Un număr cu zecimale.

Exemple

Exemplele de pe această pagină pornesc de la datele de mai jos. Rulează mai întâi acest cod, apoi exemplul.

CREATE TABLE orase (
  id INT PRIMARY KEY,
  nume VARCHAR(20),
  loc POINT NOT NULL SRID 4326,
  SPATIAL INDEX (loc)
);

INSERT INTO orase VALUES
  (1, 'Iași',        ST_GeomFromText('POINT(47.1585 27.6014)', 4326)),
  (2, 'Cluj-Napoca', ST_GeomFromText('POINT(46.7712 23.6236)', 4326)),
  (3, 'București',   ST_GeomFromText('POINT(44.4268 26.1025)', 4326)),
  (4, 'Timișoara',   ST_GeomFromText('POINT(45.7489 21.2087)', 4326)),
  (5, 'Constanța',   ST_GeomFromText('POINT(44.1598 28.6348)', 4326));

CREATE TABLE magazine (
  id INT PRIMARY KEY,
  nume VARCHAR(20),
  loc POINT NOT NULL
);

INSERT INTO magazine VALUES
  (1, 'Librăria Ana',   Point(1, 1)),
  (2, 'Florăria Dan',   Point(2, 6)),
  (3, 'Brutăria Ioana', Point(5, 3)),
  (4, 'Cafeneaua Mara', Point(4, 2)),
  (5, 'Atelierul Radu', Point(12, 1));

CREATE TABLE cartiere (
  id INT PRIMARY KEY,
  nume VARCHAR(20),
  forma POLYGON NOT NULL
);

INSERT INTO cartiere VALUES
  (1, 'Centru',   ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')),
  (2, 'Copou',    ST_GeomFromText('POLYGON((0 4,4 4,4 8,0 8,0 4))')),
  (3, 'Tătărași', ST_GeomFromText('POLYGON((3 1,7 1,7 5,3 5,3 1))')),
  (4, 'Galata',   ST_GeomFromText('POLYGON((10 0,13 0,13 3,10 3,10 0))'));

Exemplul 1: Distanța de la Iași la celelalte orașe

SELECT b.nume, ROUND(ST_Distance(a.loc, b.loc, 'kilometre'), 1) AS km
FROM orase a JOIN orase b ON a.nume = 'Iași' AND b.id <> a.id
ORDER BY km;

Rezultat

+-------------+-------+
| nume        | km    |
+-------------+-------+
| Cluj-Napoca | 305.7 |
| București   | 325.2 |
| Constanța   | 342.9 |
| Timișoara   | 515.3 |
+-------------+-------+

Exemplul 2: Cel mai apropiat magazin de un client (plan în km)

SET @client = Point(3, 3);

SELECT nume, ROUND(ST_Distance(loc, @client), 2) AS km
FROM magazine
ORDER BY km
LIMIT 3;

Rezultat

+-----------------+------+
| nume            | km   |
+-----------------+------+
| Cafeneaua Mara  | 1.41 |
| Brutăria Ioana  |    2 |
| Librăria Ana    | 2.83 |
+-----------------+------+

Exemplul 3: Distanța de la un punct la un cartier

SELECT nume, ST_Distance(forma, Point(9, 2)) AS km_pana_la_margine
FROM cartiere
ORDER BY km_pana_la_margine;

Rezultat

+-------------+--------------------+
| nume        | km_pana_la_margine |
+-------------+--------------------+
| Galata      |                  1 |
| Tătărași    |                  2 |
| Centru      |                  5 |
| Copou       |  5.385164807134504 |
+-------------+--------------------+

Greșeli frecvente

  • Calculezi distanțe GPS cu SRID 0. Rezultatul este în grade și nu se poate transforma corect în kilometri; folosește SRID 4326.
  • Folosești ORDER BY ST_Distance(...) pe tabele foarte mari fără alt filtru. Calculul se face pentru fiecare rând; restrânge mai întâi zona cu MBRContains() sau ST_Within(), care pot folosi indexul spațial.

Comenzi înrudite

  • ST_Distance_Sphere(): Returnează distanța pe o sferă (în metri) dintre două puncte; un calcul rapid, aproximativ, pentru coordonate GPS.
  • ST_Length(): Returnează lungimea unei linii (sau suma lungimilor dintr-un MULTILINESTRING); pe SRID 4326, în metri.
  • ST_Buffer(): Returnează zona formată din toate punctele aflate la cel mult o distanță dată de o geometrie (o „zonă tampon”).
  • ST_FrechetDistance() și ST_HausdorffDistance(): Măsoară cât de asemănătoare sunt două linii (de exemplu două trasee GPS); 0 înseamnă trasee identice.