SQL重叠时间跨度的数据分组

时间:2019-07-09 20:28:56

标签: sql sql-server sql-cte

我需要根据记录的开始和结束时间通过重叠时间跨度将彼此相关的数据分组在一起。 SQL小提琴在这里:http://sqlfiddle.com/#!18/87e4b/1/0

我建立的当前查询给出了错误的结果。 Callid 3的callCount应该为4。这不是因为记录6不与记录3重叠,所以不包括它,但是应该包含记录6,因为它与其他相关记录之一重叠了。因此,我认为可能需要递归CTE,但不确定如何编写。

模式:

CREATE TABLE Calls
    ([callid] int, [src] varchar(10), [start] datetime, [end] datetime, [conf] varchar(5));

INSERT INTO Calls
    ([callid],[src],[start],[end],[conf])
VALUES
    ('1','5555550001','2019-07-09 10:00:00', '2019-07-09 10:10:00', '111'),
    ('2','5555550002','2019-07-09 10:00:01', '2019-07-09 10:11:00', '111'),
    ('3','5555550011','2019-07-09 11:00:00', '2019-07-09 11:10:00', '111'),
    ('4','5555550012','2019-07-09 11:00:01', '2019-07-09 11:11:00', '111'),
    ('5','5555550013','2019-07-09 11:01:00', '2019-07-09 11:15:00', '111'),
    ('6','5555550014','2019-07-09 11:12:00', '2019-07-09 11:16:00', '111'),
    ('7','5555550014','2019-07-09 15:00:00', '2019-07-09 15:01:00', '111');

当前查询:

SELECT 
    detail_record.callid,
    detail_record.conf,
    MIN(related_record.start) AS sessionStart,
    MAX(related_record.[end]) As sessionEnd,
    COUNT(related_record.callid) AS callCount
FROM    
    Calls AS detail_record
    INNER JOIN
    Calls AS related_record     
        ON related_record.conf = detail_record.conf
        AND ((related_record.start >= detail_record.start
                AND related_record.start < detail_record.[end])
            OR (related_record.[end] > detail_record.start
                AND related_record.[end] <= detail_record.[end])
            OR (related_record.start <= detail_record.start
                AND related_record.[end] >= detail_record.[end])
            )
WHERE
    detail_record.start > '1/1/2019'
    AND detail_record.conf = '111'
GROUP BY
    detail_record.callid,
    detail_record.start,
    detail_record.conf
HAVING 
    MIN(related_record.start) >= detail_record.start
ORDER BY sessionStart DESC

预期结果:

callid  conf  sessionStart          sessionEnd              callCount
   7    111   2019-07-09T15:00:00Z  2019-07-09T15:01:00Z    1
   3    111   2019-07-09T11:00:00Z  2019-07-09T11:15:00Z    4
   1    111   2019-07-09T10:00:00Z  2019-07-09T10:11:00Z    2

1 个答案:

答案 0 :(得分:2)

这是一个孤岛问题。它不需要递归CTE。您可以使用窗口功能:

const withCSS = require('@zeit/next-css')

module.exports = withCSS({
  cssLoaderOptions: {
    url: false
  }   
})

最里面的子查询计算上一个结束。中间子查询将其与当前开始进行比较,以确定相邻行的组何时是新组的开始。然后,累积和确定分组。

并且,外部查询汇总以汇总有关每个组的信息。

Here是db <>小提琴。