重叠日期时间的最大数量,有许多开始和结束时间

Max Number of Overlapping datetimes, with many start and end times

经过一些试验和搜索后,我发现这个查询给出了我需要的结果:

SET @start := '2015-12-12 00:00:00', @end := '2015-12-12 23:59:59';

SELECT Max(simultaneous_people), 
       Max(simultaneous_event), 
       boundary 
FROM   (SELECT Count(id)                AS simultaneous_people, 
               Count(DISTINCT uniqueId) AS simultaneous_event, 
               boundary 
        FROM   mytable 
               RIGHT JOIN (SELECT row_begin AS boundary 
                           FROM   mytable 
                           WHERE  row_begin BETWEEN @start AND @end 
                           UNION 
                           SELECT row_end 
                           FROM   mytable 
                           WHERE  row_end BETWEEN @start AND @end 
                           UNION 
                           SELECT @start 
                           UNION 
                           SELECT @end 
                           UNION 
                           SELECT Max(boundary) 
                           FROM   (SELECT Max(row_begin) AS boundary 
                                   FROM   mytable 
                                   WHERE  row_begin <= @start 
                                   UNION ALL 
                                   SELECT Max(row_end) 
                                   FROM   mytable 
                                   WHERE  row_end <= @end) t) t 
                       ON row_begin <= boundary 
                          AND boundary < row_end 
        WHERE  row_status = 1 
        GROUP  BY boundary) t;

这是同一时间重叠时间段的最大数量。 但我需要在多个时间间隔之间提取此信息,例如 10。 我无法找到如何在 运行 时间内置的日历中提取此信息,查询如下:

SELECT DATE_SUB(@date, INTERVAL @num MINUTE) AS endSample, 
       DATE_SUB(@date, INTERVAL @num:=@num+@lenght MINUTE) AS startSample
FROM 
  mytable,
  (SELECT @num:=0) num
LIMIT 10;

我正在使用 MySQL,不幸的是我无法在此数据库上存储任何 data/table/procedure/view。

如果有人知道如何以有效的方式合并这两个查询,那就太好了。 谢谢!


更新:

我的架构:

CREATE TABLE mytable (
  id         INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  uniqueId   INT,
  row_status INT,
  row_begin DATETIME,
  row_end   DATETIME
);

还有一些数据是一天的,只测试小时粒度:

INSERT INTO mytable (uniqueId, row_status, row_begin, row_end)
VALUES
  (1, 1, '2015-12-12 08:00:00', '2015-12-12 12:00:00'),
  (1, 1, '2015-12-12 08:00:00', '2015-12-12 14:00:00'),
  (1, 1, '2015-12-12 08:00:00', '2015-12-12 14:00:00'),
  (2, 1, '2015-12-12 13:00:00', '2015-12-12 14:00:00'),
  (2, 1, '2015-12-12 13:00:00', '2015-12-12 16:00:00'),
  (3, 1, '2015-12-12 09:00:00', '2015-12-12 12:00:00'),
  (3, 0, '2015-12-12 08:00:00', '2015-12-12 16:00:00');

我刚刚添加了 SQL Fiddle

这里我必须用变量手动设置每个日期范围,但我需要能够设置一个 'calendar',并且能够指定日历是按天、按小时还是按分钟按分钟,通过调整@length 变量。

我的解决方案的第一部分来自 this answer

我想要的输出,以小时为时间粒度,类似于:

start_sample        | end_sample          | MAX(simultaneous_people) | MAX(simultaneout_event)
2015-12-12 08:00:00 | 2015-12-12 08:59:59 | 3                        | 1
2015-12-12 09:00:00 | 2015-12-12 09:59:59 | 4                        | 2
2015-12-12 10:00:00 | 2015-12-12 10:59:59 | 4                        | 2
2015-12-12 11:00:00 | 2015-12-12 11:59:59 | 4                        | 2
2015-12-12 12:00:00 | 2015-12-12 12:59:59 | 2                        | 1
2015-12-12 13:00:00 | 2015-12-12 13:59:59 | 4                        | 2
2015-12-12 14:00:00 | 2015-12-12 14:59:59 | 1                        | 1
...

但是如果我需要将粒度更改为天,使用此数据,我将获得

start_sample        | end_sample          | MAX(simultaneous_people) | MAX(simultaneout_event)
2015-12-12 00:00:00 | 2015-12-12 23:59:59 | 4                        | 2
2015-12-13 00:00:00 | 2015-12-12 23:59:59 | 0                        | 0
...

解决方案比我想象的要容易(希望直到现在看起来是正确的)。 我将使用我的日历生成器添加一些额外的边界,以避免我的最终数据出现空洞(否则不会显示没有条目的一天):

                       ...
                       UNION 
                       SELECT @start 
                       UNION 
                       SELECT @end 
                       UNION
                           SELECT DATE_SUB(@date, INTERVAL @num:=@num+@lenght MINUTE)
                           FROM 
                             mytable,
                             (SELECT @num:=0) num
                           LIMIT 10
                       ...

然后我必须按 date_part(在 postgres 中)ora DATE_FORMAT(在 MySQL 中)进行分组,这对我来说更有趣(我必须添加一个要配对的变量@length), 而不是我之前做的整个边界,外部查询会变成:

SELECT Max(simultaneous_people), 
       Max(simultaneous_event), 
       DATE_FORMAT(boundary,'%Y%m%d')
FROM (...) as t
GROUP BY DATE_FORMAT(boundary,'%Y%m%d');

我希望这可以帮助其他人,我花了一段时间才达到这一点。 这个查询真的很重,有很多数据,所以你 cut/segment(垂直和水平)数据越多,它的性能就越好,'WHERE row_status = 1' 应该添加到所有通过工会。