MySQL 时间序列数据库,跟踪数量/价格/数据历史——仅当新值与前一个不同时才插入新行?

Posted

技术标签:

【中文标题】MySQL 时间序列数据库,跟踪数量/价格/数据历史——仅当新值与前一个不同时才插入新行?【英文标题】:MySQL time series database, track quantity/price/data history — insert a new row only if a new value is different from the previous one? 【发布时间】:2017-08-08 00:44:08 【问题描述】:

我正在尝试创建跟踪产品库存数量(100k+ 产品)的时间序列产品数据库。它将每 30 分钟从 CSV 文件更新一次,如果 AvailQuant 或 AvailNextQuant 已更改,我只想插入一条新记录。每个新的源 CSV 文件的每一行都有一个新的日期和时间。某些库存数量可能每月仅更改一次,因此仅当时间不同时,没有必要每 30 分钟插入一个新的重复行。必须有一些简单明了的方法来做到这一点,因为我认为这是很常见的事情(价格历史跟踪网站等,仅在价格变化时更新)。

列如下:ProductID、AvailQuant、AvailDate、AvailTime、AvailNextQuant、AvailNextDate。

我首先想到使用 3 个单独的表:tmp1、tmp2 和最终时间序列表。首先将 LOAD DATA INFILE REPLACE 加载到 tmp1 表中,然后仅插入新产品,如果库存值更改为 tmp2,则更新现有产品,然后从 tmp2 表 INSERT IGNORE 到唯一索引为:ProductID + Date + Time 的最终时间序列表中。不确定如何存档,或者它是否接近正确的方法?现在我也认为使用 LOAD DATA INFILE 我应该只需要一个 tmp 表?

PS。我是 mysql 的新手,所以如果有人知道如何做到这一点,将非常感谢您对示例代码进行一些解释。

【问题讨论】:

【参考方案1】:

将 ProductID、AvailQuant 和 AvailNextQuant 设置为主键。然后在重复键上使用插入。这是一个例子

On duplicate key ignore?

【讨论】:

感谢您的建议。我是否应该将它直接用于时间序列表,它可以正常工作,直到在不同日期出现重复数量,因为不会添加新日期的重复数量。我在想,在 tmp2 表中使用某种 REPLACE 命令可能会起作用?这是我现在使用的代码:code "INSERT INTO time_series_table SELECT * FROM tmp1 ON DUPLICATE KEY UPDATE time_series_table.ProductID=time_series_table.ProductID";【参考方案2】:

所以这就是我到目前为止想出的。不是 100% 确定它是否正常工作并且不会跳过任何行,但当我测试它时,它看起来工作正常。如果有人知道更好更简单的方法,请告诉我们(必须有更简单或更简单的方法)?这种方法并不完美,因为停产的产品不会从临时表中删除。也不确定如何测试数据和代码的完整性,因为每个文件每 30 分钟加载一次,有 100k+ 行?

我设置了3个重复表,tmp1、tmp2和times_series

第 1 步,tmp1:主键 = ProductID(此处导入 CSV)

第 2 步,tmp2:主键 = ProductID(清除不需要的行)

Final, time_series: Primary key = ProductID, AvailDate, AvailTime(保存时间序列数据历史)

列如下:ProductID、AvailQuant、AvailDate、AvailTime、AvailNextQuant、AvailNextDate。

第一步,首先我们需要从CSV(制表符分隔)中获取数据到数据库。从CSV文件加载数据infile到tmp1。 REPLACE 命令和 ProductID 作为主键将替换现有的产品并插入数据库中不存在的新产品。停产的产品不会从 tmp1 中删除。我们只想要最新的数据,这就是为什么要替换。

sql1 = ”LOAD DATA LOCAL INFILE ’csv_file.txt’
       REPLACE
       INTO TABLE tmp1 
       FIELDS TERMINATED BY '\t' 
       ENCLOSED BY ''
       LINES TERMINATED BY '\n'
       IGNORE 1 ROWS";

第 2 步,然后我们需要将 tmp1 ProductID、AvailQuant 和 AvailNextQuant 与 tmp2 表进行比较,并仅选择和替换从 tmp1 到 tmp2 的更改行。 再次 REPLACE 命令和 ProductID 为主键将用新行替换旧行,并且之前不存在的新行(产品)也将插入到 tmp2 中。停产的产品不会从 tmp2 中删除。如果没有第 2 步,tmp1 表将包含仅具有不同日期和时间的新行,这将导致时间序列数据具有仅具有不同日期的重复行。此数据已准备好用于时间序列表,因为它仅包含新更改的行和未更改的现有行。未更改的现有行将在最终插入时被忽略。

sql2 = ”REPLACE tmp2
       SELECT tmp1.*
       FROM tmp1 LEFT OUTER JOIN tmp2
       ON tmp1.ProductID=tmp2.ProductID
       AND tmp1.AvailQuant=tmp2.AvailQuant
       AND tmp1.AvailNextQuant=tmp2.AvailNextQuant
       WHERE tmp2.ProductID IS NULL”;

最后,我们可以从 tmp2 到 time_series 表中插入和忽略。 因为 primary key = (ProductID, date, time) IGNORE 会忽略来自时序表中重复行的错误但在tmp2中没有变化。

sql3 = ”INSERT IGNORE INTO time_series
       SELECT * FROM tmp2”;

【讨论】:

以上是关于MySQL 时间序列数据库,跟踪数量/价格/数据历史——仅当新值与前一个不同时才插入新行?的主要内容,如果未能解决你的问题,请参考以下文章

按月透视 MySQL 中的数据

MySQL的简介及发展历

是否可以在数据库中跟踪库存并更新使用 Paypal 进行的购买的商品数量?

MySQL查找不同数量和价格的商品的总销售额

如何使用PHP将每个产品的ID,数量,标题,价格,类型从下面的数组插入数据库?

更新产品数量(php和Mysql)