Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在postgresql表中获得不重叠的不同间隔?_Sql_Postgresql_Date_Window Functions_Gaps And Islands - Fatal编程技术网

如何在postgresql表中获得不重叠的不同间隔?

如何在postgresql表中获得不重叠的不同间隔?,sql,postgresql,date,window-functions,gaps-and-islands,Sql,Postgresql,Date,Window Functions,Gaps And Islands,该表有用户会话,我需要打印不同的非重叠会话 CREATE TABLE SESSIONS( id serial NOT NULL PRIMARY KEY, ctn INT NOT NULL, day DATE NOT NULL, f_time TIME(0) NOT NULL, l_time TIME(0) NOT NULL ); INSE

该表有用户会话,我需要打印不同的非重叠会话

CREATE TABLE SESSIONS(
            id serial NOT NULL PRIMARY KEY, 
            ctn INT NOT NULL, 
            day DATE NOT NULL,
            f_time TIME(0) NOT NULL,
            l_time TIME(0) NOT  NULL
        );     
    INSERT INTO SESSIONS(id, ctn, day, f_time, l_time)
    VALUES
    (1, 707, '2019-06-18', '10:48:25', '10:56:17'),
    (2, 707, '2019-06-18', '10:48:33', '10:56:17'),
    (3, 707, '2019-06-18', '10:53:17', '11:00:49'),
    (4, 707, '2019-06-18', '10:54:31', '10:57:37'),
    (5, 707, '2019-06-18', '11:03:59', '11:10:39'),
    (6, 707, '2019-06-18', '11:04:41', '11:08:02'),
    (7, 707, '2019-06-18', '11:11:04', '11:19:39');

我的桌子看起来像这样:

id  ctn day         f_time      l_time
1   707 2019-06-18  10:48:25    10:56:17
2   707 2019-06-18  10:48:33    10:56:17
3   707 2019-06-18  10:53:17    11:00:49
4   707 2019-06-18  10:54:31    10:57:37
5   707 2019-06-18  11:03:59    11:10:39
6   707 2019-06-18  11:04:41    11:08:02
7   707 2019-06-18  11:11:04    11:19:39
现在我需要不同的非重叠用户会话,所以它应该给我

1.  start_time: 10:48:25  end_time: 11:00:49  duration: 12min,24 sec
2.  start_time: 11:03:59  end_time: 11:10:39  duration: 6min,40 sec
3.  start_time: 11:11:04  end_time: 11:19:33  duration: 8min,29 sec

这是一个缺口和孤岛问题。下面是一种使用窗口函数的方法:

select
    ctn,
    min(f_ts) start_ts,
    max(l_ts) end_ts,
    max(l_ts) - min(f_ts) duration
from (
    select 
        s.*,
        count(*) filter(where f_ts > lag_l_ts) over(partition by ctn order by f_ts) grp
    from (
        select
            s.*,
            lag(l_ts) over(partition by ctn order by f_ts) lag_l_ts
        from (
            select
                s.*,
                (day + l_time)::timestamp l_ts,
                (day + f_time)::timestamp f_ts
            from sessions s
        ) s
    ) s
) s
group by ctn, grp
order by ctn, start_ts
查询的工作方式如下:

  • 首先,我们从日期和时间部分重新构建适当的时间戳:以这种方式存储数据会使操作变得不容易(而且它不允许会话在不同的日子中传播)

  • 一个数据是标准化的,我们使用
    lag()
    获取“上一行”的结束时间戳

  • 然后,我们可以构建“相邻”记录的组:每次开始时间戳大于前一个结束时间戳时,一个新组开始

  • 最后一步是聚合

ctn | start_ts | end_ts | duration --: | :------------------ | :------------------ | :------- 707 | 2019-06-18 10:48:25 | 2019-06-18 11:00:49 | 00:12:24 707 | 2019-06-18 11:03:59 | 2019-06-18 11:10:39 | 00:06:40 707 | 2019-06-18 11:11:04 | 2019-06-18 11:19:39 | 00:08:35 ctn |开始|结束|持续时间 --: | :------------------ | :------------------ | :------- 707 | 2019-06-18 10:48:25 | 2019-06-18 11:00:49 | 00:12:24 707 | 2019-06-18 11:03:59 | 2019-06-18 11:10:39 | 00:06:40 707 | 2019-06-18 11:11:04 | 2019-06-18 11:19:39 | 00:08:35
这是一个缺口和孤岛问题。下面是一种使用窗口函数的方法:

select
    ctn,
    min(f_ts) start_ts,
    max(l_ts) end_ts,
    max(l_ts) - min(f_ts) duration
from (
    select 
        s.*,
        count(*) filter(where f_ts > lag_l_ts) over(partition by ctn order by f_ts) grp
    from (
        select
            s.*,
            lag(l_ts) over(partition by ctn order by f_ts) lag_l_ts
        from (
            select
                s.*,
                (day + l_time)::timestamp l_ts,
                (day + f_time)::timestamp f_ts
            from sessions s
        ) s
    ) s
) s
group by ctn, grp
order by ctn, start_ts
查询的工作方式如下:

  • 首先,我们从日期和时间部分重新构建适当的时间戳:以这种方式存储数据会使操作变得不容易(而且它不允许会话在不同的日子中传播)

  • 一个数据是标准化的,我们使用
    lag()
    获取“上一行”的结束时间戳

  • 然后,我们可以构建“相邻”记录的组:每次开始时间戳大于前一个结束时间戳时,一个新组开始

  • 最后一步是聚合

ctn | start_ts | end_ts | duration --: | :------------------ | :------------------ | :------- 707 | 2019-06-18 10:48:25 | 2019-06-18 11:00:49 | 00:12:24 707 | 2019-06-18 11:03:59 | 2019-06-18 11:10:39 | 00:06:40 707 | 2019-06-18 11:11:04 | 2019-06-18 11:19:39 | 00:08:35 ctn |开始|结束|持续时间 --: | :------------------ | :------------------ | :------- 707 | 2019-06-18 10:48:25 | 2019-06-18 11:00:49 | 00:12:24 707 | 2019-06-18 11:03:59 | 2019-06-18 11:10:39 | 00:06:40 707 | 2019-06-18 11:11:04 | 2019-06-18 11:19:39 | 00:08:35
你如何定义最长?喜欢前三名还是前五名?@热情,不只是不重叠,对不起,我将编辑您如何定义最长的?喜欢前三名还是前五名?@热心,不只是不重叠,抱歉我会编辑它,我确实怀疑这听起来像是一个常见问题,但不知道它有名字。现在用谷歌搜索更容易…该死,我自己永远无法构建它,我不知道etclag()是std函数的分区是什么?@ERJAN:gaps and islands在SQL中被认为是一个相当困难的问题。。。我添加了一个关于查询工作原理的逐步解释。是的,
lag()
s是一个标准的窗口函数。有没有一本书可以让我读到关于常见sql问题的源代码?thx u,我确实怀疑它听起来像是一个常见问题,但不知道它有名字。现在用谷歌搜索更容易…该死,我自己永远无法构建它,我不知道etclag()是std函数的分区是什么?@ERJAN:gaps and islands在SQL中被认为是一个相当困难的问题。。。我添加了一个关于查询工作原理的逐步解释。还有,是的,
lag()
s是一个标准的窗口函数。有没有一本关于常见sql问题的源码书?