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

时间:2017-08-08 00:44:09

标签: php mysql sql database csv

我正在尝试制作跟踪产品库存数量(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完全是新手,所以如果有人知道怎么做,那么对示例代码的一点解释将非常感激。

2 个答案:

答案 0 :(得分:0)

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

On duplicate key ignore?

答案 1 :(得分:0)

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

我已经设置了3个重复的表,tmp1,tmp2和times_series

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

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

最终,time_series:主键= ProductID,AvailDate,AvailTime(保存时间序列数据历史记录)

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

步骤1,首先我们需要将数据从CSV(制表符分隔)到数据库。将数据从CSV文件加载到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表。因为主键=(ProductID,date,time)IGNORE将忽略时间序列表中重复行的错误但在tmp2中没有改变。

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