通过SELECT..INSERT语句填充空记录

时间:2012-03-22 02:03:29

标签: mysql

在此之前,这里是数据库的简化schema带虚拟记录):

ITEMLIST

ItemID     ItemName     DateAcquired     Cost       MonthlyDep    CurrentValue
================================================================================
1          Stuff Toy    2011-12-25       100.00         10.00         100.00
2          Mouse        2011-12-23       250.00         50.00         200.00
3          Keyboard     2011-12-17       250.00         30.00         190.00
4          Umbrella     2011-12-28       150.00         20.00         110.00
5          Aircon       2011-12-29       950.00         25.00         925.00

DepreciationTransaction

ItemID     DateOfDep       MonthlyDep     
======================================
2          2012-01-31         250.00
3          2012-01-31          30.00
4          2012-01-31          20.00
5          2012-01-31          25.00
3          2012-02-29          30.00
4          2012-02-29          20.00

我需要你的建议来帮助我解决这个问题。基本上我正在创建某个LGU的折旧监控系统。当前数据库的问题在于它缺少特定折旧日期的某些记录,例如:

缺乏记录(这不是数据库中的表格)

ItemID      LackingDate
============================
1            2012-01-31
1            2012-02-29
2            2012-02-29
5            2012-02-29

由于缺少记录,我无法生成MARCH月份的折旧报告。我知道如何在DepreciationTransaction上插入缺失的记录?

到目前为止我做了什么? 无。但是计算新折旧值的简单查询 (由于缺少记录而产生错误值的

2 个答案:

答案 0 :(得分:1)

您可以构建一个temporary table,其中包含所需的日期。并使用该表 LEFT OUTER JOIN “DepreciationTransaction”表。

SELECT dt.date_value, dt.itemid, ISNULL(SUM(dt.MonthlyDep), 0)
FROM tmp_date
    LEFT OUTER JOIN
    DepreciationTransaction AS dt
    ON tmp_date.date_value = dt.DateOfDep
GROUP BY dt.date_value, dt.itemid

当然,如果您希望报告所有项目,则应使用tmp_date和items_id制作cartesian product

答案 1 :(得分:1)

这里的问题是您必须生成数据。 MySQL不是为了生成数据,你应该在应用程序级别这样做,并告诉MySQL存储它。在这种情况下,应用程序应检查是否有丢失的记录,并在需要时创建它们。

除此之外,您可以(非常)使用MySQL创建动态数据:

select il.itemId, endOfMonths.aDate from ((
  select aDate from (
    select @maxDate - interval (a.a+(10*b.a)+(100*c.a)+(1000*d.a)) day aDate from
    (select 0 as a union all select 1 union all select 2 union all select 3
     union all select 4 union all select 5 union all select 6 union all
     select 7 union all select 8 union all select 9) a, /*10 day range*/
    (select 0 as a union all select 1 union all select 2 union all select 3
     union all select 4 union all select 5 union all select 6 union all
     select 7 union all select 8 union all select 9) b, /*100 day range*/
    (select 0 as a union all select 1 union all select 2 union all select 3
     union all select 4 union all select 5 union all select 6 union all
     select 7 union all select 8 union all select 9) c, /*1000 day range*/
    (select 0 as a union all select 1 union all select 2 union all select 3
     union all select 4 union all select 5 union all select 6 union all
     select 7 union all select 8 union all select 9) d, /*10000 day range*/
    (select @minDate := (select min(dateAcquired) from il),
            @maxDate := '2012-03-01') e
  ) f
  where aDate between @minDate and @maxDate and aDate = last_day(aDate)
) endOfMonths, il)
left join dt
on il.itemId = dt.itemId and endOfMonths.aDate = dt.dateOfDep
where dt.itemId is null and last_day(il.dateAcquired) < endOfMonths.aDate

根据日期范围的长度,您可以通过删除表格(d,c,b和a)并从中删除它们来减少动态生成结果的数量(10000天意味着超过27年的记录,每个代表一天)上层公式。设置@minDate和@maxDate变量将允许您指定要过滤结果的日期。在您的情况下,此日期应该是您拥有商品的最短日期,最长日期应该是3月。

用简单的英语:如果select min(dateAcquired) from il返回'2012-03-01' - 10000 days之前的日期,那么您将不得不添加另一个联盟。

最后,只需添加insert语句(如果您确实需要插入这些记录)。