如何在SQL Server中随时间插入lat / long?

时间:2011-12-06 08:04:07

标签: sql sql-server sql-server-2008 geometry interpolation

我有两张桌子,简化如下。

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;

这会产生所有值,但在Timestamp上没有完全匹配的情况下会出现NULL。

我的目标是为值表中的每个值获取插值位置。我需要以某种方式在我的查询中插入值,这就是我陷入困境的地方。

编辑:我发现我可以添加一个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 个答案:

答案 0 :(得分:3)

你看过Spatial Tools库了吗? link
它们具有插值功能,可以满足您的需求:

  

SqlGeometry InterpolateBetweenGeom(SqlGeometry start,SqlGeometry结束,   双倍距离)

我修改了我的第一个例子,现在计算两个最近点的中点,但我认为上面的库是一个更好的选择。要使用我的函数,你传入那些NULL位置的时间戳,函数将中点作为一个geom位置返回。

这可能对类似情况的人有用:

   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 :(得分:1)

我认为您应该更改查询以在每一行返回3组值:

这些应该是小于当前时间和位置的最大时间和位置,

当前时间和地点,

并且最小的时间和位置大于当前的时间和位置。

通过这种方式,每行都有足够的信息来进行数学运算......