MySQL如何在一系列时间戳上对行进行求和?

时间:2011-07-26 21:29:26

标签: mysql sql timestamp sum aggregate

给定一个带有时间戳列的表,例如:

    timestamp           |  id  |  value  
    --------------------------------------
    2001-01-01 00:00:00 |  1   |  3
    2001-01-01 00:00:00 |  2   |  5
    --------------------------------------
    2001-01-02 00:00:00 |  1   |  6
    2001-01-02 00:00:00 |  2   |  10
    2001-01-02 00:00:00 |  3   |  7
    --------------------------------------
    2001-01-03 00:00:00 |  3   |  14
    2001-01-03 00:00:00 |  2   |  15
    --------------------------------------
    2001-01-03 00:00:00 |  1   |  9
    2001-01-03 00:00:00 |  2   |  20

和给定的聚合级别,比如 2天,我想将结果汇总(总和):

(1)给定的agg级别的移动窗口,对于上面的例子:2001-01-01至2001-01-02,2001-01-02至2001-01-03,2001-01-03至2001- 01-04将导致:

    timestamp_1         | timestamp_2         |  id  |  agg_value  
    -----------------------------------------------------------
    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  1   |  9 (=3+6)
    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  2   |  15 (=5+10)
    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  3   |  7 (=7)
    -----------------------------------------------------------
    2001-01-02 00:00:00 | 2001-01-03 00:00:00 |  1   |  6 (=6)
    2001-01-02 00:00:00 | 2001-01-03 00:00:00 |  2   |  25 (=10+15)
    2001-01-02 00:00:00 | 2001-01-03 00:00:00 |  3   |  21 (=7+14)
    -----------------------------------------------------------
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  1   |  9 (=9)
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  2   |  35 (=15+20)
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  3   |  14 (=14)

(2)对于给定范围的非重叠除法,对于上面的例子:2001-01-01到2001-01-02,2001-01-03到2001-01-04,这将导致:

    timestamp_1         | timestamp_2         |  id  |  agg_value  
    -----------------------------------------------------------

    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  1   |  9 (=3+6)
    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  2   |  15 (=5+10)
    2001-01-01 00:00:00 | 2001-01-02 00:00:00 |  3   |  7 (=7)
    -----------------------------------------------------------
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  1   |  9 (=9)
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  2   |  35 (=15+20)
    2001-01-03 00:00:00 | 2001-01-04 00:00:00 |  3   |  14 (=14)

(基本上类似于(1)没有重叠)

谢谢!


编辑:添加解决方案

至少对于(1)我有一个解决方案:

    SELECT t1.timestamp AS timestamp1,
    MAX(t2.timestamp) AS timestamp2, t1.id,
    SUM(t2.value) AS agg_value
    FROM my_table t1
    LEFT JOIN my_table t2 ON
    (t2.timestamp >= t1.timestamp AND
    t2.timestamp <= ADDDATE(t1.timestamp,INTERVAL 2 DAY) AND
    t2.id = t1.id)
    GROUP BY t1.timestamp, t1.id

(2)的解决方案可能只是过滤到上述的一部分。

1 个答案:

答案 0 :(得分:0)

这将按X天分组,获取日期部分并获取日期差异并按日差分组,加上ID。这将获得您的#2解决方案

select 
       CEILING( datediff( date( now() ), date( myTimeStamp )) / 2 ) DaysDiff,
       ID,
       min( date( myTimeStamp )) as FirstDateInGroup,
       max( date( myTimeStamp )) as LastDateInGroup,
       sum( value ) as SumVal
   FROM TimeSample
   group by DaysDiff, ID
   order by FirstDateInGroup, ID

编辑----评论

你的样品展示了如何处理2天......这样做。 “now()”只是对数据进行分组的基线。如果你希望它按年分解,那么我只会根据YEAR(YourDateColumn)作为组进行查询。如果你想要30天,只需要除以30.每月,我会分别按年份(YourDateColumn)和月份(YourDateColumn)分组。通过具有固定的“now()”范围,它只做一个数字作为起点。如果你的数据是2岁,那么日期差异就是365天* 2年= 730天...除以2和你的背部以365为基础。你可以抛出你想要的任何where子句来进一步限制时间你感兴趣的时期...

“2011-01-01”和“2011-06-30”之间的myTimeStamp只能获得今年的前6个月...这将导致您的DaysDiff分组为208天/ 2 = 104。 / p>

因此,如果你有一些其他的基线值,你可以做出分组,你可以将now()更改为'2011-01-01',它将根据2011年1月1日的基础进行计算。其中,这只会将DaysDiff计算为负值,最多为零,然后再回到正值。