经过一些实验和一些搜索,我发现这个查询给出了我需要的结果:
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,不幸的是我无法在此数据库中存储任何数据/表/过程/视图。
如果有人知道如何以有效的方式合并这两个查询将会很棒。 谢谢!
更新:
我的架构:
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。
在这里,我必须手动设置每个日期范围的变量,但我需要能够设置“日历”,并能够指定日历是日,时,小时还是分钟,调整@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
...
答案 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');
我希望这可能对其他人有所帮助,需要一段时间才能达到这一点。 这个查询对于大量数据来说非常繁重,因此对数据进行剪切/分段越多(垂直和水平),它的执行效果就越好,&#39; WHERE row_status = 1&#39;应该在工会获得约束的任何地方添加。