开发者社区> 问答> 正文

怎样按一定时间间隔跳跃查询数据?

我的项目用的是MySQL,但也想同时请教下在Oracle、SqlServer中应该如何处理如下问题:

有数据表如下所示:
希望从表中抽取数据,要求两条记录的时间间隔至少2分钟
对下面图片中的数据而言,假如我查询的时间范围是从2014-08-10 23:20:00开始的,
则希望抽取到如下结果集:
'83', '57', '10041', '74.27', '0', '2014-08-10 23:20:04'
'113', '57', '10041', '59.25', '0', '2014-08-10 23:22:06'
'145', '57', '10041', '96.21', '0', '2014-08-10 23:24:07'
'177', '57', '10041', '34.16', '0', '2014-08-10 23:26:08'
'209', '57', '10041', '39.11', '0', '2014-08-10 23:28:09'
真实的场景是:传感器每隔30秒左右会向数据库里写一条记录,我要取N天的数据绘图,如果一次性查询N天的记录再进行抽稀的话,由于结果集太大,循环次数过多,导致时耗严重。我希望能通过sql语句直接在数据库层面进行数据抽稀,程序里要处理的数据就会少很多。

问题就是,应该如何写SQL语句?

展开
收起
蛮大人123 2016-02-11 23:00:10 3472 1
1 条回答
写回答
取消 提交回答
  • 公益是一辈子的事, I am digoal, just do it. 阿里云数据库团队, 擅长PolarDB, PostgreSQL, DuckDB, ADB等, 长期致力于推动开源数据库技术、生态在中国的发展与开源产业人才培养. 曾荣获阿里巴巴麒麟布道师称号、2018届OSCAR开源尖峰人物.

    对于PostgreSQL数据库来说,这个需求很简单,写个函数就可以搞定。
    例子:

    digoal=# create table test(id serial, crt_time timestamp);
    CREATE TABLE
    digoal=# insert into test (crt_time) select generate_series(now(),now()+interval '10 min', interval '30 sec');
    INSERT 0 21
    digoal=# select * from test;
     id |          crt_time          
    ----+----------------------------
      1 | 2016-04-12 10:25:08.696388
      2 | 2016-04-12 10:25:38.696388
      3 | 2016-04-12 10:26:08.696388
      4 | 2016-04-12 10:26:38.696388
      5 | 2016-04-12 10:27:08.696388
      6 | 2016-04-12 10:27:38.696388
      7 | 2016-04-12 10:28:08.696388
      8 | 2016-04-12 10:28:38.696388
      9 | 2016-04-12 10:29:08.696388
     10 | 2016-04-12 10:29:38.696388
     11 | 2016-04-12 10:30:08.696388
     12 | 2016-04-12 10:30:38.696388
     13 | 2016-04-12 10:31:08.696388
     14 | 2016-04-12 10:31:38.696388
     15 | 2016-04-12 10:32:08.696388
     16 | 2016-04-12 10:32:38.696388
     17 | 2016-04-12 10:33:08.696388
     18 | 2016-04-12 10:33:38.696388
     19 | 2016-04-12 10:34:08.696388
     20 | 2016-04-12 10:34:38.696388
     21 | 2016-04-12 10:35:08.696388
    (21 rows)
    
    create or replace function get_sparse_data(b timestamp, e timestamp, sparse interval, lmt int) returns setof test as 
    $$
    
    declare
      res test;
      rec test;
      cn int := 0;
    begin
      for rec in select * from test where crt_time between b and e order by crt_time loop
        if res is null or rec.crt_time - res.crt_time >= sparse then
          res := rec;
          cn := cn+1;
          return next res;
        end if;
    
        if cn >= lmt then
          return;
        end if;
      end loop;
    end;
    
    $$
     language plpgsql;
    
    digoal=# select get_sparse_data('2016-04-12 10:26:38.696388', '2016-04-12 10:34:08.696388', '1 min', 5);
              get_sparse_data          
    -----------------------------------
     (4,"2016-04-12 10:26:38.696388")
     (6,"2016-04-12 10:27:38.696388")
     (8,"2016-04-12 10:28:38.696388")
     (10,"2016-04-12 10:29:38.696388")
     (12,"2016-04-12 10:30:38.696388")
    (5 rows)
    
    digoal=# select get_sparse_data('2016-04-12 10:26:38.696388', '2016-04-12 10:34:08.696388', '2 min', 5);
              get_sparse_data          
    -----------------------------------
     (4,"2016-04-12 10:26:38.696388")
     (8,"2016-04-12 10:28:38.696388")
     (12,"2016-04-12 10:30:38.696388")
     (16,"2016-04-12 10:32:38.696388")
    (4 rows)

    另外,您的场景非常像物联网,建议可以考虑使用PostgreSQL, 有几篇文章建议你可以看看:
    一个简单算法可以帮助物联网,金融 用户 节约98%的数据存储成本 (PostgreSQL,Greenplum帮你做到)
    https://yq.aliyun.com/articles/18042
    PostgreSQL 如何潇洒的处理每天上百TB的数据增量
    https://yq.aliyun.com/articles/8528
    PostgreSQL 1000亿数据量 正则匹配 速度与激情
    https://yq.aliyun.com/articles/7549
    PostgreSQL 百亿地理位置数据 近邻查询性能
    https://yq.aliyun.com/articles/2999
    PostgreSQL "物联网"应用 - 1 实时流式数据处理案例(万亿每天)
    https://yq.aliyun.com/articles/166

    2019-07-17 18:41:03
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载