2016-01-22 110 views
0

数一些尝试和一些搜索,我发现,这个查询给我确切的结果后,我需要:最大重叠日期时间,许多开始和结束时间

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:[email protected][email protected] 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

包含你的数据库模式,数据样本和期望结果。请阅读http:// stackoverflow。com/help/how-to-ask 这里是[** START **]的好地方(http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question -on-a-public-forum /) –

+0

如果您愿意,可以考虑遵循以下简单的两步操作步骤:1.如果您尚未这样做,请提供适当的CREATE和INSERT语句(和/或sqlfiddle)我们可以更容易地复制问题。 2.如果您尚未这样做,请提供与步骤1中提供的信息相符的所需结果集。 – Strawberry

+0

@ juan-carlos-oropeza和Strawberry感谢您的建议。我只是添加了CREATE语句和SQL小提琴。 – sabau

回答

0

解决方案比我想象的要容易(希望是正确的,因为直到现在)。 我会用我的日历生成器添加一些额外的界限,以避免为我最终的数据空洞(一天没有条目不会做出另外的说明):

     ... 
         UNION 
         SELECT @start 
         UNION 
         SELECT @end 
         UNION 
          SELECT DATE_SUB(@date, INTERVAL @num:[email protected][email protected] MINUTE) 
          FROM 
          mytable, 
          (SELECT @num:=0) num 
          LIMIT 10 
         ... 

然后我用得组date_part(在postgres中)或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'); 

我希望这可以帮助别人,它需要一段时间才能达到这一点。 这个查询对于大量数据来说确实很重,所以越是裁剪/分段(垂直和水平)数据,它的执行效果就越好,应该在任何地方添加'WHERE row_status = 1'工会。

相关问题