Я пытаюсь передать тип таблицы в хранимую процедуру и хотел бы, чтобы sproc искал каждую строку широты/длины и возвращал мне ближайшую точку для этой строки.
Тип:
CREATE TYPE dbo.LatLongRoadLinkType AS TABLE
(
Id INT NOT NULL,
Latitude FLOAT NOT NULL,
Longitude FLOAT NOT NULL
);
Сохраненная процедура:
ALTER PROCEDURE [dbo].[BatchNearestRoadNodes]
@Input dbo.LatLongRoadLinkType READONLY
AS
BEGIN
-- do stuff here
-- return a table of id from input, nodeid and distance
END
Для всей таблицы нужно сделать то, что здесь делается для одной широты/долготы:
DECLARE @g geography = 'POINT(13.5333414077759 54.549524307251)';
DECLARE @region geography = @g.STBuffer(5000)
SELECT TOP 1 NodeID, Point.STDistance(@g) as 'Distance'
FROM Location
WHERE Point.Filter(@region) = 1
ORDER BY Point.STDistance(@g)
В таблице Location есть важный столбец Point типа Geography, который пространственно индексирован и с которым выполняются сравнения. Я отправляю таблицу lat/longs из кода в sproc, и код ожидает возврата:
Id (original point passed in)
NodeID (of nearest point in location table)
Distance
Как мне подойти к этому? Возможно, чтобы сделать это немного проще, я мог бы просто передать SqlGeography из моего кода в sproc вместо Lat/Long, однако это убьет производительность, поскольку преобразование в это очень дорого.
EDIT: это работает, но не знаю, является ли это наиболее оптимальным решением.
ALTER PROCEDURE [dbo].[BatchNearestRoadNodes]
@Input dbo.LatLongRoadLinkType READONLY
AS
BEGIN
SELECT x.Id, x.LocationName, x.NodeID, x.Distance
FROM (SELECT I.Id,
L.LocationName,
L.NodeId,
L.Point.STDistance(geography::Point(I.Latitude, I.Longitude, 4326)) AS Distance,
ROW_NUMBER () OVER (PARTITION BY I.Id ORDER BY L.Point.STDistance(geography::Point(I.Latitude, I.Longitude, 4326)) ASC) AS Ranking
FROM @Input AS I
JOIN Location AS L
ON L.Point.STIntersects(geography::Point(I.Latitude, I.Longitude, 4326).STBuffer(5000)) = 1
) AS x WHERE Ranking = 1
END
Производительность – версия 1 и версия Джона
V1
============
original:643 found:627 in:1361 ms
original:1018 found:999 in:1700 ms
original:1801 found:1758 in:2628 ms
original:4098 found:3973 in:5271 ms
original:16388 found:15948 in:19624 ms
Jon's Edit
==========
original:643 found:627 in:1333 ms
original:1018 found:999 in:1689 ms
original:1801 found:1758 in:2559 ms
original:4098 found:3973 in:5114 ms
original:16388 found:15948 in:19054 ms
Разница минимальна. Нужно убрать последнюю цифру.