STDistance: примеры (SQL)
STDistance(other_geography geography): floatОписание функции STDistance
Функция STDistance является методом для пространственных типов данных geometry и geography в MS SQL Server. Она вычисляет кратчайшее расстояние между двумя экземплярами пространственных объектов.
Применяется в задачах геоаналитики, логистики, работы с картографическими данными для определения дистанции между точками, линиями, полигонами.
Функция принимает один обязательный аргумент: другой экземпляр пространственного данных того же типа (geometry или geography). Синтаксис: instance1.STDistance(instance2).
Возвращаемое значение имеет тип float. Для типа geography результат возвращается в метрах. Для типа geometry результат выражается в единицах измерения, определенных системой координат (SRID) объектов. Если объекты пересекаются, функция возвращает 0. Если какой-либо из экземпляров пуст, возвращается NULL.
Простые примеры применения
Расстояние между двумя точками в системе geometry (декартовы координаты).
DECLARE @point1 geometry = geometry::STGeomFromText('POINT(0 0)', 0);
DECLARE @point2 geometry = geometry::STGeomFromText('POINT(3 4)', 0);
SELECT @point1.STDistance(@point2) AS Distance;Distance 5
Расстояние между точками на Земле с использованием типа geography (координаты WGS 84).
DECLARE @geo1 geography = geography::STGeomFromText('POINT(37.61778 55.75583)', 4326); -- Москва
DECLARE @geo2 geography = geography::STGeomFromText('POINT(30.26417 59.89444)', 4326); -- Санкт-Петербург
SELECT @geo1.STDistance(@geo2) AS DistanceInMeters;DistanceInMeters 633483.437235746
Расстояние от точки до полигона. Функция возвращает 0, если точка внутри.
DECLARE @poly geometry = geometry::STGeomFromText('POLYGON((0 0, 5 0, 5 5, 0 5, 0 0))', 0);
DECLARE @point geometry = geometry::STGeomFromText('POINT(2 2)', 0);
DECLARE @pointOut geometry = geometry::STGeomFromText('POINT(7 7)', 0);
SELECT
@poly.STDistance(@point) AS DistanceToPointInside,
@poly.STDistance(@pointOut) AS DistanceToPointOutside;DistanceToPointInside DistanceToPointOutside 0 2.82842712474619
Другие пространственные функции MS SQL
MS SQL Server предлагает набор функций для анализа пространственных данных:
- STLength() — вычисляет длину линейного объекта или периметр.
- STArea() — определяет площадь экземпляра geometry или geography.
- STIntersects() — проверяет факт пересечения объектов, часто используется с пространственными индексами для быстрого фильтрации.
- STWithin() — определяет, находится ли один объект полностью внутри другого.
- STBuffer() — возвращает объект, представляющий буферную зону вокруг исходного.
STDistance предпочтительна для точного вычисления дистанции. STIntersects эффективнее для предварительной фильтрации пересекающихся или близких объектов, особенно при использовании с индексами.
Распространенные ошибки
1. Сравнение объектов разных типов (geometry с geography).
DECLARE @g geometry = geometry::Point(0, 0, 0);
DECLARE @geo geography = geography::Point(0, 0, 4326);
SELECT @g.STDistance(@geo);Сообщение об ошибке: Типы данных geometry и geography несовместимы в операции STDistance.
2. Использование объектов с разными идентификаторами SRID.
DECLARE @g1 geometry = geometry::STGeomFromText('POINT(0 0)', 4326);
DECLARE @g2 geometry = geometry::STGeomFromText('POINT(1 1)', 0);
SELECT @g1.STDistance(@g2);Сообщение об ошибке: Операция STDistance над экземплярами geometry с разными SRID недопустима.
3. Игнорирование NULL-значений, приводящее к неочевидным результатам.
DECLARE @g1 geometry = geometry::Point(0, 0, 0);
DECLARE @g2 geometry;
SELECT @g1.STDistance(@g2) AS DistanceToNull;DistanceToNull NULL
История изменений функции
В SQL Server 2012 (версия 11.x) существенно переработаны алгоритмы для типа geography. Расстояние стало рассчитываться по эллипсоидальной модели Земли (референсный эллипсоид WGS 84), что повысило точность по сравнению с прежней сферической моделью.
В SQL Server 2017 добавлена поддержка вычисления STDistance между экземплярами geometry, содержащими криволинейные сегменты (например, CIRCULARSTRING).
На производительность функции также влияют улучшения в работе пространственных индексов в последних версиях СУБД.
Сложные и специальные примеры
Поиск ближайших объектов в таблице с использованием пространственного индекса для ускорения.
-- Создание таблицы с пространственным индексом
CREATE TABLE Places (
Id INT IDENTITY PRIMARY KEY,
Name NVARCHAR(100),
Location geography
);
CREATE SPATIAL INDEX SIndx_Places_Location ON Places(Location);
-- Вставка данных
INSERT INTO Places VALUES
('Точка A', geography::Point(55.751244, 37.618423, 4326)),
('Точка B', geography::Point(55.754110, 37.620090, 4326)),
('Точка C', geography::Point(55.749580, 37.613839, 4326));
-- Поиск двух ближайших точек к заданной
DECLARE @MyPoint geography = geography::Point(55.752, 37.619, 4326);
SELECT TOP 2 Name, Location.STDistance(@MyPoint) AS DistanceMeters
FROM Places
ORDER BY DistanceMeters;Name DistanceMeters Точка B 194.836672916677 Точка A 287.847773499339
Вычисление расстояния между объектами разных подтипов: мультиточкой и полигоном.
DECLARE @multiPoint geometry = geometry::STGeomFromText('MULTIPOINT((0 0), (10 10))', 0);
DECLARE @polygon geometry = geometry::STGeomFromText('POLYGON((2 2, 8 2, 8 8, 2 8, 2 2))', 0);
SELECT @multiPoint.STDistance(@polygon) AS Distance;Distance 0
Расстояние между геометрическими объектами в трехмерном пространстве (Z-координата игнорируется в расчетах STDistance).
DECLARE @point1 geometry = geometry::Parse('POINT(0 0 100)');
DECLARE @point2 geometry = geometry::Parse('POINT(3 4 200)');
SELECT @point1.STDistance(@point2) AS Distance2D;Distance2D 5
Использование в выражении CASE для классификации расстояний.
DECLARE @source geometry = geometry::Point(0, 0, 0);
DECLARE @target geometry = geometry::Point(15, 0, 0);
SELECT
CASE
WHEN @source.STDistance(@target) = 0 THEN 'Совпадает'
WHEN @source.STDistance(@target) < 10 THEN 'Близко'
ELSE 'Далеко'
END AS ProximityCategory;ProximityCategory Далеко
Аналоги в других системах
PostgreSQL (с PostGIS): Функция ST_Distance. Важное отличие — поддержка разных единиц измерения и эллипсоидов через дополнительный аргумент.
SELECT ST_Distance(
'SRID=4326;POINT(37.61778 55.75583)'::geography,
'SRID=4326;POINT(30.26417 59.89444)'::geography
);633483.437235746
MySQL: Функция ST_Distance. В версиях до 5.7 возвращает расстояние в единицах системы координат, с 5.7 для типа geography — в метрах.
SELECT ST_Distance(
ST_GeomFromText('POINT(0 0)', 0),
ST_GeomFromText('POINT(3 4)', 0)
);5
Oracle: Функция SDO_GEOM.SDO_DISTANCE. Требует задания параметра tolerance.
SELECT SDO_GEOM.SDO_DISTANCE(
SDO_GEOMETRY(2001, 4326, SDO_POINT_TYPE(37.61778, 55.75583, NULL), NULL, NULL),
SDO_GEOMETRY(2001, 4326, SDO_POINT_TYPE(30.26417, 59.89444, NULL), NULL, NULL),
0.005
) DISTANCE FROM DUAL;DISTANCE 633483.437
SQLite (с SpatiaLite): Функция ST_Distance. Поведение зависит от загруженных проекций.