MySQL:如何填充表以使用现有数据填充缺失的行

时间:2012-04-08 07:13:53

标签: mysql sql r

我有一个大的(1GB的cvs文件)季度财务数据集,我需要填写每月数据。每行都有公司标识符和日期戳,但不同的公司有不同的报告日期(3月,6月,9月,12月对2月,5月,8月,11月)。

表:来源

Co.   |Date      |NPAT   |Debt
A     |31-Dec-09 |123    |4,000
B     |29-Feb-10 |12     |300
A     |31-Mar-10 |200    |4,500
B     |31-May-10 |11     |200
A     |30-Jun-10 |159    |4,300
C     |30-Jun-10 |-30    |4

在示例公司A中报告了3月,6月,9月和12月所以我需要将3月份的数字复制到4月和5月,6月复制到7月和8月,9月到10月以及11月和12月的数字复制到1月和2月。 对于B公司,报告期为2月,5月,8月和11月。

使用上面的例子我需要的是:

表:目的地

Co.   |Date      |NPAT   |Debt
A     |31-Dec-09 |123    |4,000
A     |31-Jan-10 |123    |4,000
A     |29-Feb-10 |123    |4,000
B     |29-Feb-10 |12     |300
A     |31-Mar-10 |200    |4,500
B     |31-Mar-10 |12     |300
A     |30-Apr-10 |200    |4,500
B     |30-Apr-10 |12     |300
A     |31-May-10 |200    |4,500
....

我使用内部联接创建了一个填充表,从而生成了所有公司和日期的唯一列表,因此我实际上从包含公司和日期组合的完整列表的空表中盯着。但是我很难从哪里开始。

我正在使用mysql和R来完成这个项目,我很高兴能找到解决方案/建议。鉴于我正在寻找相当有效的实施数据量。

存在以下挑战:  1 - 公司在整个时间段内都不存在,所以我不想无限期地复制最后期限的结果(最多2个月)。同样,在早期阶段会有没有数据的公司。  2 - 不仅报告期间可能不同,但它们也可能会发生变化,因此公司最初可能会报告3月份日历,但随后会更改为2月或1月,因此在复制之前需要检查是否已有数据存在。

感谢您的帮助。

2 个答案:

答案 0 :(得分:5)

最简单的方法是复制未来两个月的数据, 但如果公司改变其报告日期,将会出现问题。

-- Pseudo-code
CREATE VIEW Tmp1 AS
SELECT Id, 
       Date AS Reported_Date, 
       Date, 
       Value1, Value2 
FROM QuarterlyData
UNION
SELECT Id, 
       Date AS Reported_Date, 
       Date + '1 month' AS Date, -- Replace this with correct date arithmetics
       Value1, Value2 
FROM QuarterlyData
UNION
SELECT Id, 
       Date AS Reported_Date, 
       Date + '2 months' AS Date, -- Replace this with correct date arithmetics
       Value1, Value2 
FROM QuarterlyData;

以下应该更安全(它也适用于每日数据)。 如果您在表格中有所有所需的日期,请先将其与季度数据一起加入(我保留数据六个月, 因为我不知道报告日期发生变化时会发生什么: 我们最终会有超过3个月的季度吗?)。

-- Pseudo-code
CREATE VIEW Tmp2 AS 
SELECT A.Id, 
       A.Date AS Reported_Date, 
       B.Date AS Date,
       A.Value1, A.Value2
FROM   Data A, Dates B
WHERE  B.Date <= A.Date 
AND    A.Date < B.Date + '6 months';

然后,删除重复项。

CREATE VIEW Tmp_Dates_To_Keep AS
SELECT Id, Date, MAX(Reported_Date) AS Reported_Date 
FROM Tmp1;

SELECT A.Id, 
       A.Date, 
       A.Reported_Date, 
       Value1, Value2
FROM   Tmp2 A, Tmp_Dates_To_Keep B
WHERE  A.Id   = B.Id 
AND    A.Date = B.Date 
AND    A.Reported_Date = B.Reported_Date;

答案 1 :(得分:0)

我使用DATE_ADD创建一个虚拟表来连接实际的行:

SELECT DATE_ADD('2013-01-01', INTERVAL 1 HOUR) UNION SELECT DATE_ADD('2013-01-01', INTERVAL 2 HOUR) UNION SELECT DATE_ADD('2013-01-01', INTERVAL 3 HOUR) UNION SELECT DATE_ADD('2013-01-01', INTERVAL 4 HOUR) ... etc