我正在尝试制作跟踪产品库存数量(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完全是新手,所以如果有人知道怎么做,那么对示例代码的一点解释将非常感激。
答案 0 :(得分:0)
将ProductID,AvailQuant和AvailNextQuant设置为主键。然后在duplicte键上使用插入。这是一个例子
答案 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”;