在 SQL 中插入多序列数据
Interpolate Multiseries Data In SQL
我有一个系统只在数据发生变化时才存储数据。因此,数据集如下所示。
data_type_id
data_value
inserted_at
2
240
2022-01-19 17:20:52
1
30
2022-01-19 17:20:47
2
239
2022-01-19 17:20:42
1
29
2022-01-19 17:20:42
我的数据频率是每5秒一次。因此,无论是否有任何 timestamp
,我都需要通过假设此第 5 秒数据值与先前值相同来获得结果。
由于我存储的只是变化的数据,所以数据集确实应该如下所示。
data_type_id
data_value
inserted_at
2
240
2022-01-19 17:20:52
1
30
2022-01-19 17:20:52
2
239
2022-01-19 17:20:47
1
30
2022-01-19 17:20:47
2
239
2022-01-19 17:20:42
1
29
2022-01-19 17:20:42
我不想insert into
我的table,我只想在SELECT
语句中检索这样的数据。
有什么方法可以创建这个查询吗?
PS。我有很多 data_type
,因此当 OP 进行查询时,它通常会得到大约一百万行。
编辑:
有关服务器的信息 Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10
用户将确定 SELECT
DateTime。所以,没有确定的between
时间。
正如@Akina 所提到的,有时 inserted_at
之间存在一些差距。差异可能是 ~4 秒或 ~6 秒而不是某个 5 秒。既然不会经常发生,忽略这个事实就可以生成了。
WITH RECURSIVE
cte1 AS ( SELECT @start_datetime dt
UNION ALL
SELECT dt + INTERVAL 5 SECOND FROM cte1 WHERE dt < @end_datetime),
cte2 AS ( SELECT *,
ROW_NUMBER() OVER (PARTITION BY test.data_type_id, cte1.dt
ORDER BY test.inserted_at DESC) rn
FROM cte1
LEFT JOIN test ON FIND_IN_SET(test.data_type_id, @data_type_ids)
AND cte1.dt >= test.inserted_at )
SELECT *
FROM cte2
WHERE rn = 1
https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=380ad334de0c980a0ddf1b49bb6fa38e
在查询的帮助下,您可以获得 data_type_id
的所有组合和您需要的 5 秒时刻,您可以使用使您最接近 [=12] 的子查询获得所需的结果=]:
with recursive u as
(select '2022-01-19 17:20:42' as d
union all
select DATE_ADD(d, interval 5 second) from u
where d < '2022-01-19 17:20:52'),
v as
(select * from u cross join (select distinct data_type_id from table_name) t)
select v.data_type_id,
(select data_value from table_name where inserted_at <= d and data_type_id = v.data_type_id
order by inserted_at desc limit 1) as data_value,
d as inserted_at
from v
您可以将递归 CTE 替换为任何能够获得所需的所有 5 秒时刻的查询。
我有一个系统只在数据发生变化时才存储数据。因此,数据集如下所示。
data_type_id | data_value | inserted_at |
---|---|---|
2 | 240 | 2022-01-19 17:20:52 |
1 | 30 | 2022-01-19 17:20:47 |
2 | 239 | 2022-01-19 17:20:42 |
1 | 29 | 2022-01-19 17:20:42 |
我的数据频率是每5秒一次。因此,无论是否有任何 timestamp
,我都需要通过假设此第 5 秒数据值与先前值相同来获得结果。
由于我存储的只是变化的数据,所以数据集确实应该如下所示。
data_type_id | data_value | inserted_at |
---|---|---|
2 | 240 | 2022-01-19 17:20:52 |
1 | 30 | 2022-01-19 17:20:52 |
2 | 239 | 2022-01-19 17:20:47 |
1 | 30 | 2022-01-19 17:20:47 |
2 | 239 | 2022-01-19 17:20:42 |
1 | 29 | 2022-01-19 17:20:42 |
我不想insert into
我的table,我只想在SELECT
语句中检索这样的数据。
有什么方法可以创建这个查询吗?
PS。我有很多 data_type
,因此当 OP 进行查询时,它通常会得到大约一百万行。
编辑:
有关服务器的信息 Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10
用户将确定 SELECT
DateTime。所以,没有确定的between
时间。
正如@Akina 所提到的,有时 inserted_at
之间存在一些差距。差异可能是 ~4 秒或 ~6 秒而不是某个 5 秒。既然不会经常发生,忽略这个事实就可以生成了。
WITH RECURSIVE
cte1 AS ( SELECT @start_datetime dt
UNION ALL
SELECT dt + INTERVAL 5 SECOND FROM cte1 WHERE dt < @end_datetime),
cte2 AS ( SELECT *,
ROW_NUMBER() OVER (PARTITION BY test.data_type_id, cte1.dt
ORDER BY test.inserted_at DESC) rn
FROM cte1
LEFT JOIN test ON FIND_IN_SET(test.data_type_id, @data_type_ids)
AND cte1.dt >= test.inserted_at )
SELECT *
FROM cte2
WHERE rn = 1
https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=380ad334de0c980a0ddf1b49bb6fa38e
在查询的帮助下,您可以获得 data_type_id
的所有组合和您需要的 5 秒时刻,您可以使用使您最接近 [=12] 的子查询获得所需的结果=]:
with recursive u as
(select '2022-01-19 17:20:42' as d
union all
select DATE_ADD(d, interval 5 second) from u
where d < '2022-01-19 17:20:52'),
v as
(select * from u cross join (select distinct data_type_id from table_name) t)
select v.data_type_id,
(select data_value from table_name where inserted_at <= d and data_type_id = v.data_type_id
order by inserted_at desc limit 1) as data_value,
d as inserted_at
from v
您可以将递归 CTE 替换为任何能够获得所需的所有 5 秒时刻的查询。