我有一个非常大的表,其中包含时间戳和值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。
答案 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. 它还取决于系统支持子查询的程度。