在一个查询中查找每月多个月的“有效”行数

时间:2015-07-22 18:14:20

标签: mysql sql

我有一个mySQL数据库,每行包含一个激活和停用日期。这指的是行所代表的对象处于活动状态的时间段。

activate     deactivate   id
2015-03-01   2015-05-10   1
2013-02-04   2014-08-23   2

我想在每个月的任何时间找到活动的行数。实施例

Jan: 4
Feb: 2
Mar: 1
etc...

我想出了如何在一个月内完成这项工作,但是我在单一查询中一年内所有12个月都在努力解决这个问题。我想在单个查询中使用它的原因是性能,因为信息是立即使用的,而缓存在这种情况下没有意义。这是我一次有一个月的代码。它会检查激活日期是否在相关月份的月末之前,并且停用日期不在相关期间的开始之前。

SELECT * from tblName WHERE activate <= DATE_SUB(NOW(), INTERVAL 1 MONTH)
AND deactivate >= DATE_SUB(NOW(), INTERVAL 2 MONTH) 

如果有人知道如何改变这一点并进行分组,我可以无限期地进行分组,我会很感激。我不知道如何分组。

1 个答案:

答案 0 :(得分:2)

如果你有一个你关心的月份表,你可以这样做:

select m.*,
       (select count(*)
        from table t
        where t.activate_date <= m.month_end and
              t.deactivate_date >= m.month_start
       ) as Actives
from months m;

如果您没有这样的桌子,您可以动态创建一个:

select m.*,
       (select count(*)
        from table t
        where t.activate_date <= m.month_end and
              t.deactivate_date >= m.month_start
       ) as Actives
from (select date('2015-01-01') as month_start, date('2015-01-31') as month_end union all
      select date('2015-02-01') as month_start, date('2015-02-28') as month_end union all
      select date('2015-03-01') as month_start, date('2015-03-31') as month_end union all
      select date('2015-04-01') as month_start, date('2015-04-30') as month_end
     ) m;

编辑:

一种可能更快的方法是计算激活和停用的累积总和,然后采用每月的最大值:

select year(date), month(date), max(cumes)
from (select d, (@s := @s + inc) as cumes
      from (select activate_date as d, 1 as inc from table t union all
            select deactivate_date, -1 as inc from table t
           ) t cross join
           (select @s := 0) param
      order by d
     ) s
group by year(date), month(date);