【问题标题】:MySQL table data transformation -- how can I dis-aggregate MySQL time data?MySQL 表数据转换——如何分解 MySQL 时间数据?
【发布时间】:2010-03-09 01:12:07
【问题描述】:

我们正在编写一个 MySQL 数据仓库应用程序,该应用程序存储与时间和生产数量数据(在下面的第一个表)在其上应用聚合(SUM、COUNT、AVG)函数。我们现在希望分解时间数据以进行另一种类型的分析。

我们目前的数据表设计:

+---------+---------+------------+---------------------+---------------------+--------+------+
| User ID | Work ID | Machine ID | Event Start Time    | Event End Time      | Output | Time |
+---------+---------+------------+---------------------+---------------------+--------+------+
| 080025  | ABC123  | M01        | 2008-01-24 16:19:15 | 2008-01-24 16:34:45 |   2120 |  930 | 
+---------+---------+------------+---------------------+---------------------+--------+------+  

我们想做的重新处理分解是基于分钟粒度而不是当前生产事件(“事件开始时间”和“事件结束时间”)粒度来转换表格内容。现有表行的重新处理结果如下所示:

+---------+---------+------------+---------------------+--------+  
| User ID | Work ID | Machine ID | Production Minute   | Output |
+---------+---------+------------+---------------------+--------+
| 080025  | ABC123  | M01        | 2010-01-24 16:19    |    133 |
| 080025  | ABC123  | M01        | 2010-01-24 16:20    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:21    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:22    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:23    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:24    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:25    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:26    |    133 |
| 080025  | ABC123  | M01        | 2010-01-24 16:27    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:28    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:29    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:30    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:31    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:22    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:33    |    133 |       
| 080025  | ABC123  | M01        | 2010-01-24 16:34    |    133 |       
+---------+---------+------------+---------------------+--------+  

因此,重新处理将采用以生产事件粒度创建的现有数据行,并将粒度修改为分钟,同时消除冗余(事件结束时间、时间)列。它假定生产速率恒定,并将输出除以分钟差加一来填充新表的输出列。

我知道这可以在代码中完成...但它可以完全在 MySQL 插入语句中完成(或者完全在 MySQL 中)吗?我正在考虑一个 INSERT ... INTO 构造,但一直卡住。另一个复杂性是操作中要包含数百台机器,因此一天中的每一分钟都会有多行(每台机器一个)。

任何想法将不胜感激。谢谢。

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    您可以创建一个表,其中包含从数据集开始到结束的每一分钟的行,并针对该行运行联接:

    select user_id, work_id, machine_id, production_minute, output
    from prod_event p
    join prod_minute m on p.start <= m.production_minute and m.production_minute <= p.end;
    

    填充 prod_minute 表可能很有趣:

    create table counter ( i int not null auto_increment primary key );
    insert into counter values ( 0 );
    insert into counter select NULL from counter;
    # ...  repeat until your counter table contains enough minutes
    
    create table prod_minute ( production_minute datetime not null primary key );
    insert into prod_minute select date_add( '2000-01-01', interval i minute ) from counter;
    

    【讨论】:

    • 谢谢马丁!这种方法非常适合单台机器。另一个复杂性是我们报告了 219 台机器,其中一些介于 0 和 219 之间的机器可能同时运行。因此,production_minute 列可能具有 1 到 219 次之间的相同值,具体取决于该分钟内运行的机器数量。我们可以添加另一列作为 PK 以使 production_minute 不唯一,但是我们如何根据该分钟实际运行的机器数量为 production_minute 重复相同的时间戳可变次数?
    • 如果您的所有数据都在单个 prod_event 表中,那么单个连接应该涵盖您的所有 user_id、work_id、machine_id 和输出。尝试一下小提取物 - 它应该可以工作。
    • 这种方法看起来可行,但我在加入时遇到了困难。具体来说,两个表之间存在多对多关系,基于连接逻辑:当 prod_event 行跨度超过一分钟时,有多个 prod_minute 行连接到它;并且当在任何给定分钟内有多台机器在运行时,会有多个 prod_event 行连接到 prod_minute 行。 prod_event 表有 500 万行,其中一个月有 43,000 分钟。有什么想法(除了大幅缩减数据集)?
    • 我不确定你的问题是什么。您是否要求比问题中显示的更好的桌子设计?如果是这样,我认为您需要更改问题 - 或提出新问题。
    • 此外,一些面向列的数据库 - InfoBright、Vertica - 将非常有效地存储和查询您的最终表格。两者都提供试用版或开源版本:我想你会感到惊讶。
    猜你喜欢
    • 1970-01-01
    • 2014-02-22
    • 2017-05-13
    • 1970-01-01
    • 2013-07-31
    • 2019-12-31
    • 2018-11-08
    • 1970-01-01
    • 2012-01-13
    相关资源
    最近更新 更多