如何查询 SQL 服务器数据库以获得时差总和,但前提是它们相差小于 2 分钟
How to query SQL Server database to get a sum of time differences but only if they are less than 2 min different
我有以下查询数据是:
SELECT *
FROM MYTABLE
WHERE tagid = '65'
输出:
tagid floatvalue t_stamp
-------------------------------
65 25.51477051 1455897455214
65 35.71407318 1455897485215
65 36.05856323 1455897515215
65 35.72781372 1455897545214
65 35.99771118 1455897575215
65 35.87993622 1455897605215
65 36.23326111 1455897665215
65 35.8652153 1455897695215
65 35.73075485 1455897725216
65 35.94765472 1455897785216
65 36.36379242 1455897815217
65 35.93685913 1455897845216
65 36.64154816 1455898025219
65 36.44329071 1455898055218
65 36.07524872 1455898085219
65 36.40992355 1455898115217
65 38.13336182 1455898145217
t_stamp
列是 Unix 的 big int time * 1000
。
如果机器 运行ning,则此数据每 ~30 秒 (30,000) 记录一次。我试图查询这个时间差的总和,如果它们距离它前面的行不到两分钟(120,000)。如果它超过两分钟,那么我假设机器已关闭并且该行将是下一个总和的新开始时间。
我的目标是使用时间戳获得总 运行 时间的总和。
我完全不知道从哪里开始。我很难尝试让这个解释对我来说甚至有意义,更不用说你们了,如果我把它弄得一团糟,我深表歉意。
如果您没有lag()
,还有其他方法可以获取之前的时间戳。
;with step1 as (
select
t_stamp,
case
when t_stamp - lag(t_stamp) over (partition by tagid order by t_stamp) > 120000
then 1 else 0
end as brk
from mytable
), step2 as (
select t_stamp, sum(brk) over (partition by tagid order by t_stamp) as grp,
from step1
)
select
grp, min(t_stamp) as start_time, max(t_stamp) as end_time,
max(t_stamp) - min(t_stamp) as total_time
from step2
group by tagid, grp;
这是 "Gaps and Islands" 标题下的一个相当典型的问题。你会发现很多与你的问题相似的例子。
今天我偶然发现了这个 Oracle article 十多年前的东西。它使用了一种您可能会感兴趣的略有不同的方法。
编辑:
这里是逻辑的快速分解。
第 1 步使用 lag
按时间顺序将每个标记与前一个值进行比较。当它发现一个大于阈值的间隙时,它被标记为 1。所有其他的都为零(null 也可以。)这有效地标记了一个新块的开始,也就是 "grp".
第 2 步以相同顺序计算 运行 总数。因此 运行 总数只会在每次新块开始时发生变化,因此块中的每一行都会获得相同的值。此值用于 group by
,然后计算时间差作为最小和最大时间戳之间的跨度。
试试 cursor.
declare @sum bigint
declare @t_stamp bigint
declare @last bigint
declare @diff bigint
select @sum = 0
declare MyCursor cursor for select t_stamp from mytable where tagid=65
open MyCursor
fetch next from MyCursor into @t_stamp
while @@fetch_Status = 0
begin
if (not (@last is null))
begin
select @diff = @t_stamp - @last
if (@diff < 120000)
begin
select @sum = @sum + @diff
end
end
select @last = @t_stamp
fetch next from MyCursor into @t_stamp
end
close MyCursor
deallocate MyCursor
print @sum
我有以下查询数据是:
SELECT *
FROM MYTABLE
WHERE tagid = '65'
输出:
tagid floatvalue t_stamp
-------------------------------
65 25.51477051 1455897455214
65 35.71407318 1455897485215
65 36.05856323 1455897515215
65 35.72781372 1455897545214
65 35.99771118 1455897575215
65 35.87993622 1455897605215
65 36.23326111 1455897665215
65 35.8652153 1455897695215
65 35.73075485 1455897725216
65 35.94765472 1455897785216
65 36.36379242 1455897815217
65 35.93685913 1455897845216
65 36.64154816 1455898025219
65 36.44329071 1455898055218
65 36.07524872 1455898085219
65 36.40992355 1455898115217
65 38.13336182 1455898145217
t_stamp
列是 Unix 的 big int time * 1000
。
如果机器 运行ning,则此数据每 ~30 秒 (30,000) 记录一次。我试图查询这个时间差的总和,如果它们距离它前面的行不到两分钟(120,000)。如果它超过两分钟,那么我假设机器已关闭并且该行将是下一个总和的新开始时间。
我的目标是使用时间戳获得总 运行 时间的总和。
我完全不知道从哪里开始。我很难尝试让这个解释对我来说甚至有意义,更不用说你们了,如果我把它弄得一团糟,我深表歉意。
如果您没有lag()
,还有其他方法可以获取之前的时间戳。
;with step1 as (
select
t_stamp,
case
when t_stamp - lag(t_stamp) over (partition by tagid order by t_stamp) > 120000
then 1 else 0
end as brk
from mytable
), step2 as (
select t_stamp, sum(brk) over (partition by tagid order by t_stamp) as grp,
from step1
)
select
grp, min(t_stamp) as start_time, max(t_stamp) as end_time,
max(t_stamp) - min(t_stamp) as total_time
from step2
group by tagid, grp;
这是 "Gaps and Islands" 标题下的一个相当典型的问题。你会发现很多与你的问题相似的例子。
今天我偶然发现了这个 Oracle article 十多年前的东西。它使用了一种您可能会感兴趣的略有不同的方法。
编辑:
这里是逻辑的快速分解。
第 1 步使用 lag
按时间顺序将每个标记与前一个值进行比较。当它发现一个大于阈值的间隙时,它被标记为 1。所有其他的都为零(null 也可以。)这有效地标记了一个新块的开始,也就是 "grp".
第 2 步以相同顺序计算 运行 总数。因此 运行 总数只会在每次新块开始时发生变化,因此块中的每一行都会获得相同的值。此值用于 group by
,然后计算时间差作为最小和最大时间戳之间的跨度。
试试 cursor.
declare @sum bigint
declare @t_stamp bigint
declare @last bigint
declare @diff bigint
select @sum = 0
declare MyCursor cursor for select t_stamp from mytable where tagid=65
open MyCursor
fetch next from MyCursor into @t_stamp
while @@fetch_Status = 0
begin
if (not (@last is null))
begin
select @diff = @t_stamp - @last
if (@diff < 120000)
begin
select @sum = @sum + @diff
end
end
select @last = @t_stamp
fetch next from MyCursor into @t_stamp
end
close MyCursor
deallocate MyCursor
print @sum