Как я могу интерполировать широту / долготу с течением времени в SQL Server? - PullRequest
4 голосов
/ 06 декабря 2011

У меня есть две таблицы, упрощенные, как показано ниже.

CREATE TABLE value(
    Timestamp DATETIME2,
    Value float NOT NULL,
    PRIMARY KEY(Timestamp)
);

CREATE TABLE location(
    Timestamp DATETIME2,
    Position GEOMETRY NOT NULL,
    PRIMARY KEY(Timestamp)
); 

Выполнение простого LEFT JOIN, такого как:

SELECT V.Timestamp, V.Value, L.Position 
FROM   value V
       LEFT JOIN location L ON V.Timestamp = L.Timestamp;

Это дает все значения, но есть NULL'sприсутствует там, где нет точного совпадения по Timestamp.

Моя цель - получить интерполированную позицию для каждого значения в таблице значений.Мне нужно как-то интерполировать значения в моем запросе, и именно здесь я застреваю.

РЕДАКТИРОВАТЬ: с тех пор я обнаружил, что могу добавить оператор CASE для проверки на NULL

SELECT 
    V.Timestamp, 
    V.Value, 
    CASE WHEN L.Position IS NULL THEN 
        (<something clever here>) 
    ELSE 
        L.Position 
    END As Position

FROM value V
     LEFT JOIN location L ON V.Timestamp = L.Timestamp;

Ответы [ 2 ]

3 голосов
/ 06 декабря 2011

Вы смотрели библиотеку пространственных инструментов? ссылка
У них есть функция интерполяции, которая выглядит так, как вам нужно:

SqlGeometry InterpolateBetweenGeom (начало SqlGeometry, конец SqlGeometry, двойное расстояние)

Я исправил свой первый пример, чтобы теперь вычислить среднюю точку двух ближайших точек, но я думаю, что приведенная выше библиотека является гораздо лучшим вариантом. Чтобы использовать мою функцию, вы передаете временные метки для этих пустых позиций, а функция возвращает среднюю точку в качестве позиции геома.

Это может быть полезно для кого-то в аналогичной ситуации:

   if object_id('dbo.fn_CalcMidPointByTime') is not null
        drop function dbo.fn_CalcMidPointByTime;
    go  
    create function [dbo].[fn_CalcMidPointByTime] (@baseTimestamp datetime2)
    returns geometry
    as
    begin
        declare @return geometry,
                @fromPoint geometry,
                @toPoint geometry;

        declare @stage table (i tinyint, position geometry);

        -- stage the high / low points
        insert into @stage (i, position)
            select  row_number() over(order by d.[Timestamp] asc), position.ToString()
            from    (   select top(2) [Timestamp]
                        from    dbo.Location
                        order by abs(datediff(ms, [Timestamp], @baseTimestamp)) asc
                    ) as d([Timestamp])
            join    dbo.Location l on
                    d.[Timestamp] = l.[Timestamp];

        select @fromPoint = position from @stage where i = 1;
        select @toPoint = position from @stage where i = 2;

        -- create linestring from the two points
        declare @ls geometry = geometry::Parse(@fromPoint.STUnion(@toPoint).ToString()).STConvexHull().ToString();

        -- draw a rectangle around the two points, and choose the center
        select @return = @ls.STEnvelope().STCentroid();
        return @return;
    end
    go
1 голос
/ 07 декабря 2011

Я думаю, вам следует изменить свой запрос, чтобы он возвращал 3 набора значений в каждой строке:

это должно быть самое большое время и позиция, которые меньше текущей,

текущее время и позиция,

и наименьшее время и позиция больше текущей.

таким образом, в каждом ряду будет достаточно информации для математики ...

...