MySQL:计算给定时间戳的中间值(线性插值)

时间:2015-02-22 21:43:15

标签: mysql

根据下表,我想在00:00:00准确选择每个ID的值。如果在此确切时间有条目,则返回该条目,否则使用线性插值(00:00:00之前和之后的最近值之间的虚拟图线)进行计算。如果在给定时间之后没有值,则返回最后一个值,或者使用最后两个点的线性插值。

ID|Timestamp|Value
1|2015-01-01 23:00:00|90
1|2015-01-02 01:00:00|110
2|2015-01-01 23:00:00|210
2|2015-01-02 01:00:00|190
3|2015-01-02 00:00:00|50
4|2015-01-01 23:00:00|100
5|2015-01-01 22:00:00|80
5|2015-01-01 23:00:00|90

结果:

ID|Value
1|100
2|200
3|50
4|100
5|100

这仅适用于MySQL以及如何实现?

1 个答案:

答案 0 :(得分:0)

首先,让我们将它分成单个条目,如#3与双条目(其余):

( SELECT ID, value FROM tbl GROUP BY ID HAVING COUNT(*) = 1 )
UNION ALL
( ... ) -- This needs interpolation code, below
ORDER BY ID;

分离这对行很棘手,因为没有好的方法可以做“groupwise-max”。所以,相反,我将使用@variables并按顺序遍历表。

要舍入到最近的午夜可能是ROUND(... / 86400) * 86400。潜在的问题是你所在的time_zone。我不想解决这个问题。

SELECT ID, val FROM (
SELECT  ID,
        IF(ID != @prevID, '1st', '2nd') AS picker,  -- See WHERE filter, below
        @ts = timestamp,   -- Need an INT here, not sure that is what I have
        @dts = @ts - @prev_ts,
        @dval = value - @prev_val,
        @midnight := ROUND(@ts / 86400) * 86400,  -- DST issues?
        value + (@midnight - @ts) * (@dval / @dts) AS val, -- interpolate
        @prev_id = ID,
        @prev_ts = @ts,
        @prev_val = value
    FROM ( SELECT @prevID := 0 ) AS Initialize
    JOIN tbl
    ORDER BY ID, timestamp
) AS x
WHERE picker = '2nd'
ORDER BY ID

将该怪物作为UNION的第二部分。