使用参考日期和设置时间段按自定义期间范围分组数据

时间:2018-04-27 14:00:35

标签: mysql

例如,如果我有一个如下所示的表:

+----+--------+---------------------+
| id | volume |      createdAt      |
+----+--------+---------------------+
|  1 |   0.11 | 2018-01-26 13:56:01 |
|  2 |   0.34 | 2018-01-28 14:22:12 |
|  3 |   0.22 | 2018-03-11 11:01:12 |
|  4 |   0.19 | 2018-04-13 12:12:12 |
|  5 |   0.12 | 2014-04-21 19:12:11 |
+----+--------+---------------------+

我想执行一个查询,该查询可以接受起始点,然后遍历给定的天数,然后按该日期范围进行分组。

例如,我希望结果如下:

+------------+------------+--------+
| enddate    | startdate  | volume |
+------------+------------+--------+
| 2018-04-25 | 2018-04-12 |   0.31 |
| 2018-04-11 | 2018-03-29 |   0.00 |
| 2018-03-28 | 2018-03-15 |   0.00 |
| 2018-03-14 | 2018-03-01 |   0.22 |
| 2018-02-28 | 2018-02-15 |   0.00 |
| 2018-02-14 | 2018-02-01 |   0.00 |
| 2018-01-31 | 2018-01-18 |   0.45 |
| ...        | ...        |    ... |
+------------+------------+--------+

本质上,我希望能够输入start_date例如2018-04-25,time_interval例如INTERVAL。 14,如上图所示,然后查询将汇总该时间范围内的卷。

我知道如何将DATE_SUB()DATE_ADD()options: { legend: { display: true, labels: { generateLabels: function (chart) { ... 函数一起使用,但我无法弄清楚如何执行我认为必要的循环。

请帮忙。

2 个答案:

答案 0 :(得分:0)

你需要做的就是确定start_date(你传递的参数)和整个表中的end_date,并通过添加时间间隔来循环它们。

看看下面存储的例程:

import Cocoa

class ViewController2: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

    }

}

我希望这会有所帮助。如果我错过任何边缘案件,请发表评论。

答案 1 :(得分:0)

对于给定的数据,您可以使用datediff和floor函数确定基于时间的分组:

floor(datediff(createdat, date '2018-04-25')/14) grp

从组号中,您可以确定期间的标准和结束日期:

date_add(date '2018-04-25', interval (grp*14) day) startdate
date_add(date '2018-04-25', interval ((grp+1)*14) day) enddate

代表半开放范围,其中startdate是包含的,enddate是独占的。

将这些放在一个可用的查询中:

select startdate, enddate, sum(volume)
  from (select t1.*
             , date_add(date '2018-04-25', interval (grp*14) day) startdate
             , date_add(date '2018-04-25', interval ((grp+1)*14) day) enddate
          from (select t.*
                     , datediff(t.createdat, date '2018-04-25') diff
                     , floor(datediff(t.createdat, date '2018-04-25')/14) grp
                from table1 t) t1) t2
 group by startdate, enddate
 order by startdate desc;

不幸的是,这并没有得到空的时期。要获得空白时段,您需要一种生成行的方法。但是,MySQL没有一种简单的方法来生成行(至少在MySQL 8中添加公共表表达式和递归SQL之前),但是有些数据库对象已经有很多行,例如information_schema.columns视图可能有足够的行满足您的需要,如果它没有,则交叉连接或两个交叉连接将很容易地乘以生成的记录数。与返回的每行递增的变量配对将提供所需的组:

select @rn:=@rn+1 rn
     , stop
     , date_add(date '2018-04-25', interval (@rn*14) day) startdate
     , date_add(date '2018-04-25', interval ((@rn+1)*14) day) enddate
  from information_schema.columns c
     , (select @rn:=min(floor(datediff(createdat, date '2018-04-25')/14))-1
             , max(floor(datediff(createdat, date '2018-04-25')/14)) stop
          from table1) limits
 where @rn < stop;

外部加入原始数据并按期间日期分组产生:

select startdate
     , enddate
     , sum(volume) volume
  from table1
  right join (
    select @rn:=@rn+1 rn
         , stop
         , date_add(date '2018-04-25', interval (@rn*14) day) startdate
         , date_add(date '2018-04-25', interval ((@rn+1)*14) day) enddate
      from information_schema.columns c
        -- , information_schema.columns d -- if needed add another cartesian join
         , (select @rn:=min(floor(datediff(createdat, date '2018-04-25')/14))-1
                 , max(floor(datediff(createdat, date '2018-04-25')/14)) stop
              from table1) limits
     where @rn < stop) periods
    on startdate <= createdat
    and createdat < enddate
  group by startdate, enddate
  order by startdate desc;

查看SQL Fiddle以查看此操作