【问题标题】:Postgresql Table Same Data last adjacent occurance and first In One rowPostgresql 表相同数据最后相邻出现和第一个在一行
【发布时间】:2017-12-06 16:16:09
【问题描述】:

我有一个程序每分钟通过 PING 检查网络中计算机的状态。 每次它都会向 DB 插入一个新行,如下所示(我使用的是 postgresql)

id_status   status   checking_time(timestamp)   id_device(int)
1           OK       '2017-01-01 00:00:00'      1
2           OK       '2017-01-01 00:00:00'      2
3           OK       '2017-01-01 00:00:00'      3

4           Failed   '2017-01-01 00:01:00'      1
5           OK       '2017-01-01 00:01:00'      2
6           OK       '2017-01-01 00:01:00'      3

7           Failed   '2017-01-01 00:02:00'      1
8           OK       '2017-01-01 00:02:00'      2
9           OK       '2017-01-01 00:02:00'      3

10          Failed   '2017-01-01 00:03:00'      1
11          OK       '2017-01-01 00:03:00'      2
12          OK       '2017-01-01 00:03:00'      3

13          OK       '2017-01-01 00:04:00'      1
14          OK       '2017-01-01 00:04:00'      2
15          OK       '2017-01-01 00:04:00'      3

我希望结果如下

status   from_time(timestamp)    to_time(timestamp)      id_device(int)
OK       '2017-01-01 00:00:00'   '2017-01-01 00:01:00'   1
Failed   '2017-01-01 00:01:00'   '2017-01-01 00:04:00'   1
OK       '2017-01-01 00:04:00'   NOW                     1

OK       '2017-01-01 00:00:00'   NOW                     2
OK       '2017-01-01 00:00:00'   NOW                     3

我怎样才能得到这个输出?

【问题讨论】:

    标签: sql postgresql gaps-and-islands


    【解决方案1】:

    这是间隙和孤岛问题。可以这样解决:

    select t.status, 
       t.from_time, 
       coalesce(CAST(lead(from_time) over (partition by id_device order by from_time) AS varchar(20)), 'NOW') to_date, 
       t.id_device
    from
    (
        select t.status, min(checking_time) from_time, t.id_device
        from
        (
            select *, row_number() over (partition by id_device, status order by checking_time) - 
                      row_number() over (partition by id_device order by checking_time) grn
            from data
        ) t
        group by t.id_device, grn, t.status
    ) t
    order by  t.id_device, t.from_time
    

    dbffile demo

    关键是最嵌套的子查询,我使用两个row_number 函数来隔离设备上相同状态的连续出现。一旦你有了grn 的值,剩下的就很简单了。

    结果

    status  from_time           to_time             id_device
    ------------------------------------------------------------
    OK      2017-01-01 00:00:00 2017-01-01 00:01:00 1
    Failed  2017-01-01 00:01:00 2017-01-01 00:04:00 1
    OK      2017-01-01 00:04:00 NOW                 1
    OK      2017-01-01 00:00:00 NOW                 2
    OK      2017-01-01 00:00:00 NOW                 3
    

    类似问题

    SQL query to get min, max rows

    【讨论】:

    • 谢谢@Radim Bača 它的工作就像魅力一样。
    猜你喜欢
    • 2021-09-21
    • 1970-01-01
    • 2022-01-08
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多