Sql server 如何查询SQL Server数据库以获得时间差之和,但仅当时间差小于2分钟时

Sql server 如何查询SQL Server数据库以获得时间差之和,但仅当时间差小于2分钟时,sql-server,datetime,aggregates,Sql Server,Datetime,Aggregates,我有以下查询到的数据: 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 1

我有以下查询到的数据:

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
time*1000
的一个大整数

如果机器正在运行,则每30秒(30000)记录一次该数据。如果时间差与前一行的距离小于两分钟(120000),我将尝试查询时间差的总和。如果它大于两分钟,那么我假设机器已关闭,该行将是下一个总和的新开始时间

我的目标是使用时间戳获得总运行时间的总和


我完全不知道从哪里开始。我花了很长时间试图让这个解释对我来说甚至是有意义的,更不用说你们了,如果我把它弄得一团糟,请道歉。

如果你没有
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;
在“缺口和孤岛”标题下,这是一个相当典型的问题。你会发现很多与你的问题类似的例子

完全巧合的是,我今天发现了这个十多年前的甲骨文。它使用了一种稍微不同的方法,您可能会觉得有趣

编辑:

下面是逻辑的快速分解

步骤1使用
lag
,按时间顺序将每个戳记与上一个值进行比较。当它发现间隙大于阈值时,它将被标记为1。所有其他的都会得到零(null也可以)。这实际上标志着一个新块(也称为“grp”)的开始

步骤2以相同的顺序计算运行总数。因此,每次新块启动时,运行总数只会发生变化,因此块内的每一行都会得到相同的值。该值在
group by
中使用,然后计算时间差作为最小和最大时间戳之间的跨度。

请尝试

声明@sum bigint
声明@t_stamp bigint
声明@last bigint
声明@diff bigint
选择@sum=0
声明MyCursor光标用于从mytable中选择t_戳记,其中tagid=65
打开我的光标
从MyCursor获取下一个到@t_stamp
而@@fetch\u Status=0
开始
如果(不是(@last为空))
开始
选择@diff=@t_stamp-@last
如果(@diff<120000)
开始
选择@sum=@sum+@diff
结束
结束
选择@last=@t_stamp
从MyCursor获取下一个到@t_stamp
结束
关闭我的光标
取消分配我的游标
打印@sum

您能否根据上述数据显示预期输出?您能否显示您尝试了哪些方法使您接近解决方案?预期输出将是tagid和所有“准时”模块的总和。丹,我完全不知道从哪里开始。对时差求和不是问题,但确定什么是时差的时间块我不知道,除了它将少于120000这似乎是我想要尝试和做的。我将不得不深入研究数据并核实。我还需要通读lag()的相关知识,通过这个查询来理解它。谢谢Shawnt,我会尽快发布。@Xgrunt24我已经调整了查询,使每个
tagid
生成一行,因为一条评论建议您需要它。在验证数据后,这实际上正是我所需要的。现在要弄清楚这个查询到底在做什么。。。再次感谢您的时间和帮助!
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