SQL SELECT行,其中连续列之间的差异小于X

时间:2016-12-22 13:08:00

标签: sql postgresql

基本上Mysql: Find rows, where timestamp difference is less than x,但我想停在时间戳差大于X的第一个值。

我到目前为止:

SELECT * 
FROM (
  SELECT *, 
         (LEAD(datetime) OVER (ORDER BY datetime)) - datetime AS difference 
  FROM history
) AS sq 
WHERE difference < '00:01:00'

这似乎正确地返回了所有行与行之间的差异&#34;后面&#34;它不到一分钟,但这意味着我仍然会在datetime中获得大跳跃,这是我不想要的 - 我想选择最近的&#34;运行&#34;行,其中&#34;运行&#34;被定义为&#34; datetime中的时间戳相差不到一分钟&#34;。

例如,我有一些行,其假设时间戳如下:

24, 22, 21, 19, 18, 12, 11, 9, 7...

我的差异限制是3,即我想要运行时间戳与#34;之间差异的行。小于3;因此只是:

24, 22, 21, 19, 18

这在SQL中是否可行?

3 个答案:

答案 0 :(得分:1)

您可以使用lag获取上一行的时间戳,并检查当前行是否在3分钟之内。如果条件失败,请重置组。完成此分组后,您可以找到最新的此类组,使用max来获取它。然后从最新的组中获取所有这些行。

如果必须对表格中的每个ID进行此操作,请在窗口函数partition bylagsum中加入max子句。

with grps as (
select x.*,sum(col) over(order by dt) grp
from (select t.*
      --checking if the current row's timestamp is within 3 minutes of the next row
      ,case WHEN dt BETWEEN LAG(dt) OVER (ORDER BY dt) 
       AND LAG(dt) OVER (ORDER BY dt) + interval '3 minute' THEN 0 ELSE 1 END col
      from t) x
)
select dt 
from (select g.*,max(grp) over() maxgrp --getting the latest group
      from grps g
     ) g
where grp = maxgrp

即使它有一行,上面的内容也会让你获得最新组中的成员。为了避免这样的结果,得到最多有一行的组。

with grps as (
select x.*,sum(col) over(order by dt) grp
from (select t.*
      ,case WHEN dt BETWEEN LAG(dt) OVER (ORDER BY dt) 
       AND LAG(dt) OVER (ORDER BY dt) + 3 THEN 0 ELSE 1 END col
      from t) x
)
,grpcnts as (select g.*,count(*) over(partition by grp) grpcnt from grps g)
select dt from (select g.*,max(grp) over() maxgrp 
                from grpcnts g 
                where grpcnt > 1
               ) g 
where grp = maxgrp

答案 1 :(得分:0)

您可以使用基于var app = { getCustomers: function(){}, ... }; lead()值的标记来执行此操作。我相信这可以做你想要的:

lag()

答案 2 :(得分:0)

这可以通过recursive CTEs轻松解决(这将逐个选择您的行,并在范围interval '1 min'中没有行时停止):

with recursive h as (
    select * from (
      select   *
      from     history
      order by history.datetime desc
      limit    1
    ) s
  union all
    select * from (
      select   history.*
      from     h
      join     history on history.datetime >= h.datetime - interval '1 min'
      and      history.datetime < h.datetime
      order by history.datetime desc
      limit    1
    ) s
)
select * from h

如果您有history.datetime的索引,这应该会有效。但是,如果您关心性能,则应该针对基于窗口函数的性能进行测试。 (当我看到这个问题所需的子查询和窗口函数时,我个人很头疼。我的回答很讽刺的是postgresql不直接支持招募CTE中的ORDER BY子句,所以我不得不使用2无意义子查询&#34;隐藏&#34;他们)。

rextester