我每 15 分钟在 MySQL 数据库中记录一次电能计数器 (kWh)。 有时,记录会因多种原因而失败(断电、计算机重新启动以进行更新......)并且值丢失。
表格如下:
id Time Energy
27800 13.02.2024 23:30:01 651720048
27801 13.02.2024 23:45:00 651720672
(missing)
27802 14.02.2024 00:15:02 651721917
27803 14.02.2024 00:30:00 651722540
27804 14.02.2024 00:45:00 651723129
27805 14.02.2024 01:00:02 651723769
27806 14.02.2024 01:15:01 651724405
27807 14.02.2024 01:30:01 651725030
(missing)
27808 14.02.2024 02:00:01 651726275
27809 14.02.2024 02:15:02 651726880
27810 14.02.2024 02:30:01 651727519
27811 14.02.2024 02:45:00 651728130
27812 14.02.2024 03:00:02 651728751
27813 14.02.2024 03:15:02 651729381
我正在寻找一个 MySQL 查询,它返回特定(可变)时间跨度(例如 15 分钟、60 分钟、24 小时、1 个月...)内的消耗(能量计数器值之间的差值/差异),该查询还考虑了通过插值法缺失值。
结果应如列
Consumption 15m
和 Consumption 1h
: 中所示
id Time Energy Consumption 15m Consumption 1h
27800 13.02.2024 23:30:01 651720048 -
27801 13.02.2024 23:45:00 651720672 624
(missing) 651721294.5 622.5 -
27802 14.02.2024 00:15:02 651721917 622.5
27803 14.02.2024 00:30:00 651722540 623
27804 14.02.2024 00:45:00 651723129 589
27805 14.02.2024 01:00:02 651723769 640 2474,5
27806 14.02.2024 01:15:01 651724405 636
27807 14.02.2024 01:30:01 651725030 625
(missing) 651725652.5 622.5
27808 14.02.2024 02:00:01 651726275 622.5 2506
27809 14.02.2024 02:15:02 651726880 605
27810 14.02.2024 02:30:01 651727519 639
27811 14.02.2024 02:45:00 651728130 611
27812 14.02.2024 03:00:02 651728751 621 2476
27813 14.02.2024 03:15:02 651729381 630
我想以某种方式需要找到两个给定时间点的最接近的两个值(例如 14.02.2024 00:00:00 和 14.02.2024 01:00:00)并创建能量计数器的插值来构建然后它的区别。
哪个查询可以达到预期的结果?
一种选择是生成开始时间和结束时间之间的所有 15 分钟间隔 - 将间隔连接到填充缺失行的表数据 - 估算缺失的消耗量并填充缺失的行...
WITH -- S a m p l e D a t a :
tbl as
( Select 27800 "ID", To_Date('13.02.2024 23:30:01', 'dd.mm.yyyy hh24:mi:ss') "TIME", 651720048 "ENERGY" From Dual Union All
Select 27801, To_Date('13.02.2024 23:45:00', 'dd.mm.yyyy hh24:mi:ss'), 651720672 From Dual Union All
--
Select 27802, To_Date('14.02.2024 00:15:02', 'dd.mm.yyyy hh24:mi:ss'), 651721917 From Dual Union All
Select 27803, To_Date('14.02.2024 00:30:00', 'dd.mm.yyyy hh24:mi:ss'), 651722540 From Dual Union All
Select 27804, To_Date('14.02.2024 00:45:00', 'dd.mm.yyyy hh24:mi:ss'), 651723129 From Dual Union All
Select 27805, To_Date('14.02.2024 01:00:02', 'dd.mm.yyyy hh24:mi:ss'), 651723769 From Dual Union All
Select 27806, To_Date('14.02.2024 01:15:01', 'dd.mm.yyyy hh24:mi:ss'), 651724405 From Dual Union All
Select 27807, To_Date('14.02.2024 01:30:01', 'dd.mm.yyyy hh24:mi:ss'), 651725030 From Dual Union All
--
Select 27808, To_Date('14.02.2024 02:00:01', 'dd.mm.yyyy hh24:mi:ss'), 651726275 From Dual Union All
Select 27809, To_Date('14.02.2024 02:15:02', 'dd.mm.yyyy hh24:mi:ss'), 651726880 From Dual Union All
Select 27810, To_Date('14.02.2024 02:30:01', 'dd.mm.yyyy hh24:mi:ss'), 651727519 From Dual Union All
Select 27811, To_Date('14.02.2024 02:45:00', 'dd.mm.yyyy hh24:mi:ss'), 651728130 From Dual Union All
Select 27812, To_Date('14.02.2024 03:00:02', 'dd.mm.yyyy hh24:mi:ss'), 651728751 From Dual Union All
Select 27813, To_Date('14.02.2024 03:15:02', 'dd.mm.yyyy hh24:mi:ss'), 651729381 From Dual
),
创建 CTE(将其命名为间隔)以生成所有 15 分钟间隔...
-- Generate intervals of 15 minutes between first and last TIME column of your data
intervals AS
( Select MIN_TIME + ( (LEVEL - 1) * 15 ) / (24*60) "TIME",
To_Char(MIN_TIME + ( (LEVEL - 1) * 15 ) / (24*60), 'dd.mm.yyyy hh24:mi:ss') "DATE_TIME"
From
( Select To_Date( To_Char(Min(Trunc(t.TIME, 'mi')), 'dd.mm.yyyy hh24:mi'), 'dd.mm.yyyy hh24:mi') "MIN_TIME",
To_Date(To_Char(Max(Trunc(t.TIME, 'mi')), 'dd.mm.yyyy hh24:mi'), 'dd.mm.yyyy hh24:mi') "MAX_TIME",
CEIL( ( ( Max(Trunc(t.TIME, 'mi')) - Min(Trunc(t.TIME, 'mi')) ) *24 *60 ) / 4) "DIFF"
From tbl t
)
Connect By LEVEL <= CEIL(DIFF / 4) + 1
)
...将间隔连接到表数据中,进行近似(需要时)并填充缺失的行...
-- M a i n S Q L :
SELECT Coalesce(To_Char(t.ID), 'APPROX-') || ROW_NUMBER() OVER(Partition By Case When t.TIME Is Null Then 1 End Order By t.ID) "ID",
Coalesce(To_Char(t.TIME, 'dd.mm.yyyy hh24:mi:ss'), i.DATE_TIME) "TIME",
Coalesce( t.ENERGY,
LAST_VALUE(t.ENERGY) OVER( Order By Coalesce(t.TIME, i.TIME) Rows Between Unbounded Preceding And 1 Preceding ) +
CEIL( ( LEAD(t.ENERGY) OVER(Order By Coalesce(t.TIME, i.TIME) ) - Coalesce( t.ENERGY, LAG(t.ENERGY) OVER(Order By Coalesce(t.TIME, i.TIME) ) ) ) / 2 )
) "ENERGY",
Case When t.TIME Is Null
Then CEIL( ( LEAD(t.ENERGY) OVER(Order By Coalesce(t.TIME, i.TIME) ) -
Coalesce( t.ENERGY, LAG(t.ENERGY) OVER(Order By Coalesce(t.TIME, i.TIME) ) ) ) / 2
)
End "APPROX_CONSUMPTION"
FROM intervals i
Left Join tbl t ON( Coalesce(Trunc(t.TIME, 'mi'), i.TIME) = i.TIME )
/* R e s u l t :
ID TIME ENERGY APPROX_CONSUMPTION
------------------- ------------------- ---------- ------------------
278001 13.02.2024 23:30:01 651720048
278012 13.02.2024 23:45:00 651720672
APPROX-1 14.02.2024 00:00:00 651721295 623
278023 14.02.2024 00:15:02 651721917
278034 14.02.2024 00:30:00 651722540
278045 14.02.2024 00:45:00 651723129
278056 14.02.2024 01:00:02 651723769
278067 14.02.2024 01:15:01 651724405
278078 14.02.2024 01:30:01 651725030
APPROX-2 14.02.2024 01:45:00 651725653 623
278089 14.02.2024 02:00:01 651726275
2780910 14.02.2024 02:15:02 651726880
2781011 14.02.2024 02:30:01 651727519
2781112 14.02.2024 02:45:00 651728130
2781213 14.02.2024 03:00:02 651728751
2781314 14.02.2024 03:15:02 651729381 */