MySQL - 获取给定日期范围的并发事件总数

时间:2014-12-16 21:35:25

标签: mysql date concurrency count

我有一个事件表,每个事件都有一个给定的开始和结束日期。

CREATE TABLE dataset (    
id int(11) unsigned NOT NULL AUTO_INCREMENT,
event varchar(64) NOT NULL DEFAULT '',
valid_from date DEFAULT NULL,
valid_to date DEFAULT NULL,
PRIMARY KEY (id)
);

INSERT INTO dataset (event, valid_from, valid_to) VALUES
('Test1', '2014-12-01', '2014-12-01'),
('Test2', '2014-12-02', '2014-12-02'),
('Test3', '2014-12-03', '2014-12-03'),
('Test4', '2014-12-04', '2014-12-04'),
('Test5', '2014-12-05', '2014-12-05'),
('Test6', '2014-12-01', '2014-12-01'),
('Test7', '2014-12-01', '2014-12-07');

我需要查询帮助才能获得给定日期范围内的最大并发事件数。如果开始日期和结束日期与此查询的预期结果相同:

SET @d1 = '2014-12-01';
SET @d2 = '2014-12-01';
SELECT COUNT(*) as valid_events FROM dataset WHERE @d2 >= valid_from AND valid_to >= @d1;

这将返回3,它在12月1日与Test1,Test6和Test7匹配。但如果我延长范围,它就不再为我工作了:

SET @d1 = '2014-12-01';
SET @d2 = '2014-12-07';
SELECT COUNT(*) as valid_events FROM dataset WHERE @d2 >= valid_from AND valid_to >= @d1;

这会返回7,因为所有事件都与开始日期和结束日期重叠,但我希望它们只有在彼此重叠时才会被计算。

            Test1 Test2 Test3 Test4 Test5 Test6 Test7  Result
2014-12-01    X                             X     X     3
2014-12-02          X                             X     2
2014-12-03                X                       X     2
2014-12-04                      X                 X     2
2014-12-05                            X           X     2
2014-12-06                                        X     1
2014-12-07                                        X     1

因此,如果我在12月1日和7日之间请求最大并发事件数量,我希望得到3而不是7的结果。

3 个答案:

答案 0 :(得分:0)

在其中一个开始日期发生最大并发事件数。因此,您可以通过一些连接和聚合来执行此操作:

select d.valid_from, count(*) as numoverlaps
from (select distinct d.valid_from from dataset d
     ) d join
     dataset d2
     on d.valid_from >= d2.valid_from and d.valid_from <= d2.valid_to
group by d.valid_from;

您可以通过添加order bylimit

来获得最大值
select d.*
from (select d.valid_from, count(*) as numoverlaps
      from (select distinct d.valid_from from dataset d
           ) d join
           dataset d2
           on d.valid_from >= d2.valid_from and d.valid_from <= d2.valid_to
      group by d.valid_from
     ) d
order by numoverlaps desc
limit 1;

答案 1 :(得分:0)

 SELECT * FROM calendar WHERE dt BETWEEN  '2014-11-30' AND '2015-01-01';
+------------+
| dt         |
+------------+
| 2014-11-30 |
| 2014-12-01 |
| 2014-12-02 |
| 2014-12-03 |
| 2014-12-04 |
| 2014-12-05 |
| 2014-12-06 |
| 2014-12-07 |
| 2014-12-08 |
| 2014-12-09 |
| 2014-12-10 |
| 2014-12-11 |
| 2014-12-12 |
| 2014-12-13 |
| 2014-12-14 |
| 2014-12-15 |
| 2014-12-16 |
| 2014-12-17 |
| 2014-12-18 |
| 2014-12-19 |
| 2014-12-20 |
| 2014-12-21 |
| 2014-12-22 |
| 2014-12-23 |
| 2014-12-24 |
| 2014-12-25 |
| 2014-12-26 |
| 2014-12-27 |
| 2014-12-28 |
| 2014-12-29 |
| 2014-12-30 |
| 2014-12-31 |
| 2015-01-01 |
+------------+

SELECT x.dt
     , COUNT(*) total 
  FROM calendar x
  JOIN dataset y 
    ON x.dt BETWEEN y.valid_from AND y.valid_to 
 GROUP 
    BY dt;
+------------+-------+
| dt         | total |
+------------+-------+
| 2014-12-01 |     3 |
| 2014-12-02 |     2 |
| 2014-12-03 |     2 |
| 2014-12-04 |     2 |
| 2014-12-05 |     2 |
| 2014-12-06 |     1 |
| 2014-12-07 |     1 |
+------------+-------+

所以只是ORDER BY ... LIMIT - 你知道其余的

答案 2 :(得分:0)

来自&#34;草莓的提示&#34;帮助我找到了一个解决方案,我最终看起来像这样:

SET @d1 = '2014-12-01';
SET @d2 = '2014-12-07';

SELECT x.selected_date, COUNT(*) total 
  FROM (
    select * from 
    (select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) selected_date from
    (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
    (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
    (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
    (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
    (select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
    where selected_date between @d1 and @d2
  ) x
  JOIN dataset y 
    ON x.selected_date BETWEEN y.valid_from AND y.valid_to 
 GROUP 
    BY selected_date
 ORDER
    BY total DESC
 LIMIT 1;

它基本上是他的解决方案,但不需要额外的日历表。为了获得两个给定日期之间的日期列表,我使用了这个解决方案:https://stackoverflow.com/a/13814885/3342150

由于