Możesz przechowywać swoje obiekty w GEOGRAPHY
kolumnę i utwórz SPATIAL INDEX
nad tą kolumną.
Niestety, SQL Server
implementuje indeksy przestrzenne poprzez kafelkowanie powierzchni i przechowywanie identyfikatorów kafelków w zwykłym B-Tree
indeks, więc zwykły ORDER BY STDistance
nie będzie działać (cóż, będzie działać, ale nie będzie korzystać z indeksu).
Zamiast tego musisz wykonać zapytanie podobne do tego:
DECLARE @mypoint GEOGRAPHY
SET @mypoint = geography::STGeomFromText('POINT(@mylat, @mylon)', 4326);
WITH num (distance) AS
(
SELECT 1000
UNION ALL
SELECT distance + 1000
FROM num
WHERE distance <= 50000
)
SELECT TOP 1 m.*
FROM num
CROSS APPLY
(
SELECT TOP 1 *
FROM mytable
WHERE myroad.STDistance(@mypoint) <= distance
ORDER BY
STDistance(@mypoint)
) m
W ten sposób SQL Server
najpierw przeszuka drogi w obrębie 1
kilometr od punktu, a następnie w ciągu 2
kilometrów itp., za każdym razem przy użyciu indeksu.
Aktualizacja:
Jeśli masz wiele punktów w tabeli i chcesz znaleźć najbliższy punkt dla każdego z nich:
WITH num (distance) AS
(
SELECT 1000
UNION ALL
SELECT distance + 1000
FROM num
WHERE distance <= 50000
)
SELECT mp.mypoint, m.*
FROM @mypoints mp
CROSS APPLY
(
SELECT TOP 1 m.*
FROM num
CROSS APPLY
(
SELECT TOP 1 *
FROM mytable
WHERE myroad.STDistance(@mypoint) <= distance
ORDER BY
STDistance(@mypoint)
) m
) m