【问题标题】:Queries to select records at specific time intervals?查询以特定时间间隔选择记录?
【发布时间】:2020-09-10 12:36:10
【问题描述】:

我有以下数据:

X,        Y,        Receiver, Timestamp 
1.534268, 51.03796, 126,      2017-06-01 02:01:01 
1.534268, 51.03793, 126,      2017-06-01 02:03:01 
1.534268, 51.03799, 133,      2017-06-01 02:05:01 
1.534268, 51.03716, 133,      2017-06-01 02:09:01 
1.534268, 51.03766, 126,      2017-06-01 02:10:01 
1.534268, 51.03766, 126,      2017-06-01 02:17:01 
1.534268, 51.03795, 126,      2017-06-01 02:19:01 
1.534268, 51.03791, 133,      2017-06-01 02:22:01 
1.534268, 51.03746, 126,      2017-06-01 02:24:01 
1.534268, 51.03796, 133,      2017-06-01 02:31:01 

我需要 SQL 查询来做两件事:

  1. 以大约 10 分钟的间隔选择记录,所以我最终得到如下结果:
X,        Y,        Receiver, Timestamp 
1.534268, 51.03796, 126,      2017-06-01 02:01:01 
1.534268, 51.03766, 126,      2017-06-01 02:10:01 
1.534268, 51.03795, 126,      2017-06-01 02:19:01 
1.534268, 51.03796, 133,      2017-06-01 02:31:01 

然后我将如何修改查询以选择 15 分钟、30 分钟和每小时间隔的数据?

  1. 根据上面的结果,我如何计算每个接收者下的记录数,即
Receiver 126: 3,
Receiver 133: 1 

【问题讨论】:

  • 您识别记录开头的规则不清楚。有时,它是在 10 分钟内。有时不是。您需要提供有关如何拆分数据的更多信息。
  • 这张表有主键吗,写查询效率更高
  • 时间戳永远不会精确相隔 10 分钟。所以我需要相隔最接近 10 分钟的连续记录。第一条记录是:02:01:01,因此选择的下一条记录应该是 02:10:01,因为它与第一条记录的差最接近 10 分钟。如果这有意义?
  • 我们需要看看您的尝试...否则您只是要求我们为您编写代码。

标签: sql sql-server timestamp


【解决方案1】:

“类似这样的东西”。嗯,最简单的做法是每十分钟从“日历时钟”中获取第一条记录。这将是 00:00、00:10、00:20 等之后的第一条记录。

为此,您可以使用first_value()select distinct

select distinct
       first_value(x) over (partition by dd, hh, mm order by timestamp) as x,
       first_value(y) over (partition by dd, hh, mm order by timestamp) as y,
       first_value(receiver) over (partition by dd, hh, mm order by timestamp) as receiver,
       min(timestamp) over (partition by dd, hh, mm),
       count(*) over (partition by dd, hh, mm) as cnt

from t cross apply
     (values (convert(date, timestamp), datepart(hour, timestamp), datepart(minute, timestamp) / 6)
     ) v(dd, hh, mm);

这不会完全返回您指定的结果,但它似乎符合问题中提到的条件。

编辑:

令我震惊的是,您可能需要 10 分钟的间隔从第一个时间戳开始。如果是这样:

select (case when seqnum = 1 then x end) as x,
       (case when seqnum = 1 then y end) as y,
       (case when seqnum = 1 then receiver end) as receiver,
       min(timestamp),
       count(*)
from (select t.*,
             datediff(second, min_ts, timestamp) / (10 * 60) as grp,
             row_number() over (partition by datediff(second, min_ts, timestamp) / (10 * 60) order by timestamp) as seqnum,
      from (select t.*,
                   min(timestamp) over () as min_ts
            from t
           ) t
     ) t
group by grp;

我认为这会返回您指定的组。 按 grp 分组;

【讨论】:

    【解决方案2】:

    使用下面的查询,

    结果1:

    select t1.* from table t1
    inner join t2
    on (datediff(minute, starttime, endtime) = 10);
    

    结果2:

    select x, t, reciever, count(1)
    from
    (select t1.* from table t1
    inner join t2
    on (datediff(minute, starttime, endtime) = 10)) qry
    group by x, t, reciever;
    

    【讨论】:

    • 将数据整理成图像是件好事,但在 SO 上,代码和数据都应该是格式化的文本,而不是图像。未来要记住的事情。
    猜你喜欢
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多