Puedes almacenar tus objetos en una GEOGRAPHY
columna y crea un SPATIAL INDEX
sobre esta columna.
Desafortunadamente, SQL Server
implementa índices espaciales colocando mosaicos en la superficie y almacenando los identificadores de mosaicos en un B-Tree
simple índice, tan simple ORDER BY STDistance
no funcionará (bueno, funcionará pero no usará el índice).
En su lugar, tendrás que hacer una consulta similar a esta:
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
De esta forma, SQL Server
primero buscará carreteras dentro de 1
kilómetro desde su punto, luego dentro de 2
kilómetros, etc., cada vez usando el índice.
Actualización:
Si tiene varios puntos en una tabla y desea encontrar el punto más cercano para cada uno de ellos:
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