选择最接近的非空值到时间戳

时间:2014-10-18 17:18:04

标签: mysql sql

我有一个非常大的表,其中包含时间戳和值V.有些V可能为null:

timestamp,V
sometime_1,value1
sometime_2,value2
sometime_3,NULL
sometime_4,value4

我想要一个查询来选择给定时间戳T的值V,但是如果它是NULL,请在T的两边最接近T的时间获取值。例如,如果我有

2010-09-01 00:00:01,v1
2010-09-01 00:00:02,v2
2010-09-01 00:00:03,NULL
2010-09-01 00:00:04,NULL
2010-09-01 00:00:05,v3

我想查询时间戳" 3"返回" v2"因为2接近3而不是5,但是想要查询时间戳" 4"返回v3因为5更接近。

时间也不保证是连续的,例如,我们可能有:

2010-09-01 00:00:01,v1
2010-09-01 00:00:04,v2
2010-09-01 00:00:30,NULL
2010-09-01 00:00:42,NULL
2010-09-01 00:00:50,v3

在这种情况下,v3最接近30和42.

目前,我通过将Python连接到SQL并从所讨论的时间戳开始在两个方向上启动for循环并返回不返回NULL的最接近的值来实现此目的。但是,如果我可以在SQL中执行此操作,那将更加清晰。我不能写一个存储过程;这必须是一个查询。

我这样做是因为我需要给定时间戳的最接近(暂时)有效值,但有时时间戳的值为NULL。

4 个答案:

答案 0 :(得分:2)

与@par解决方案类似但有时间:

SELECT v
FROM (
 (SELECT v, TIMEDIFF(T, `timestamp`) AS tdiff
   FROM table_name
   WHERE `timestamp` <= T AND v IS NOT NULL
   ORDER BY `timestamp` DESC
   LIMIT 1)
UNION ALL
 (SELECT v, TIMEDIFF(`timestamp`, T) AS tdiff
   FROM table_name
   WHERE `timestamp` > T AND v IS NOT NULL
   ORDER BY `timestamp` ASC
   LIMIT 1)
) u
ORDER BY tdiff
LIMIT 1

此处为T提供了搜索值V的时间戳。

要加快速度,您必须在timestamp列上设置索引。

答案 1 :(得分:0)

尝试

SELECT * FROM YourTable WHERE YourTable.value != NULL ORDER BY ABS(queriedTime - YourTable.time) ASC LIMIT 1

目前我没有可用的SQL,因此上述查询可能无效(未测试)。

答案 2 :(得分:0)

鉴于订购了时间戳,您可以执行以下操作。

这假定时间戳是整数,但您可以将日期时间转换为整数。我没有测试过,但想法就在那里:

SELECT * FROM
(
    (SELECT * FROM YourTable WHERE value != NULL && time <= queriedTime LIMIT 1)
    UNION
    (SELECT * FROM YourTable WHERE value != NULL && time > queriedTime LIMIT 1)
) ORDER BY ABS(time - queriedTime) ASC LIMIT 1

答案 3 :(得分:0)

您可以创建类似

的视图
 SELECT T2.T,T2.V FROM TAB AS T2 WHERE T2.V IS NOT NULL 
 UNION 
 SELECT T0.T,(
         SELECT T1.V FROM TAB AS T1 WHERE T1.V IS NOT NULL 
         ORDER BY ABS(T0.T-T1.T) LIMIT 1
        ) FROM TAB AS T0 WHERE T0.V IS NULL;

条款

  ORDER BY ABS(T0.T-T1.T)

当然可能会返回多个条目,这些条目的时间距离完全相同,在这种情况下,不同的RDBMS可能会有不同的排序方式,最终会得到不同的值V. 它还取决于系统支持子查询的程度。