我正在我的公司开发一个脚本,它将从我们的SCM中获取有关源代码活动的信息,例如一段时间内给定产品的更改行数。在同一天内发生的给定产品的所有更改将合并到mySQL表中的单个记录中,如下所示:
+------------+-------+------+
| date | prod | line |
+------------+-------+------+
| 2011-11-25 | prod2 | 471 |
| 2011-11-28 | prod2 | 389 |
+------------+-------+------+
然后,我使用内部联接和求和来复制具有累积结果的表:
+------------+-------+------+
| date | prod | line |
+------------+-------+------+
| 2011-11-25 | prod2 | 471 |
| 2011-11-28 | prod2 | 860 |
+------------+-------+------+
现在,我想创建一个每个产品每天都有一条记录的表。我已经能够通过加入日历表来做到这一点。但是,在创建新记录的位置,行字段应填充该产品的最新累积值,而不是某些硬编码的默认值,如NULL或0:
+------------+-------+------+
| date | prod | line |
+------------+-------+------+
| 2011-11-25 | prod2 | 471 |
| 2011-11-26 | prod2 | 471 |
| 2011-11-27 | prod2 | 471 |
| 2011-11-28 | prod2 | 860 |
+------------+-------+------+
到目前为止,我已经以两种令人不满意的方式解决了这个问题:
一旦我的桌子变得足够大,第一个解决方案变得非常低效。第二个解决方案完成了工作,但我一直在努力寻找更优雅的解决方案。以下是使用NULL生成表的代码:
INSERT INTO final SELECT d.date,f.prod,p.line
FROM calendar AS d
CROSS JOIN
(SELECT DISTINCT prod FROM cumulative) AS f
LEFT JOIN cumulative AS p USING (date,prod) ;
有什么想法吗?我正在使用MySQL。
答案 0 :(得分:0)
似乎最明智的做法是每天存储一行,如果没有更改行则为零。这将消除在日历表上加入的需要。
所以代替你的源表看起来像这样
+------------+-------+------+
| date | prod | line |
+------------+-------+------+
| 2011-11-25 | prod2 | 471 |
| 2011-11-28 | prod2 | 389 |
+------------+-------+------+
它看起来像这样。
+------------+-------+------+
| date | prod | line |
+------------+-------+------+
| 2011-11-25 | prod2 | 471 |
| 2011-11-26 | prod2 | 0 |
| 2011-11-27 | prod2 | 0 |
| 2011-11-28 | prod2 | 389 |
+------------+-------+------+
至于运行总和本身,您的报表编写者可能比SQL更快地执行此操作。如果MySQL支持窗口函数,你只需编写类似
的东西select date, prod,
sum(line) over (partition by prod order by date)
from prod
尽管如此,即便如此,您的报告撰稿人可能会更快。
在不支持窗口函数的平台上,您只需要在子查询中求和。
select p1.prod, p1.date,
(select sum(line) from prod
where prod = p1.prod and date <= p1.date) as num_lines
from prod p1
order by p1.prod, p1.date