[英]SQL-Oracle Update table from itself using LAG()
假设我们有一个像这样的表:
| Year | Month | Day | ID_Office | Operations | Operations yesterday |
|------|-------|-----|-----------|------------|----------------------|
| 2016 | 12 | 31 | 9555 | 500 | 0 |
| 2017 | 1 | 1 | 9555 | 600 | 0 |
| 2017 | 1 | 2 | 9555 | 750 | 0 |
| 2017 | 1 | 3 | 9556 | 800 | 0 |
我想使用上一行的“操作”更新“昨天的操作”中的值。 因此结果表必须是这样的:
| Year | Month | Day | ID_Office | Operations | Operations yesterday |
|------|-------|-----|-----------|------------|----------------------|
| 2016 | 12 | 31 | 9555 | 500 | 0 |
| 2017 | 1 | 1 | 9555 | 600 | 500 |
| 2017 | 1 | 2 | 9555 | 750 | 600 |
| 2017 | 1 | 3 | 9556 | 800 | 0 |
我将以下代码与函数LAG()配合使用,但未更新正确的值。
Update table1 F1
Set f1.operations_yesterday =
(Select LAG(f1.operations, 1, 0) OVER(ORDER BY year, month, day)
From table1 F2
Where
F1.year= F2.year And
F1.month= F2.month And
F1.day= F2.day);
您能从我的代码中给我一些关于到底是什么错误的建议吗? 在“插入到”语句中使用lag()函数取得了成功,但是在这种情况下,我必须提供Update语句解决方案。
注意:请注意,可能要订购三个以上的字段。 我仅以年,月和日为例,但是还有更多与日期无关的字段。 同样,重要的是要详细说明并非每天都有价值。
先感谢您!
一旦在子查询中传递了年,月和日的值,滞后函数将只有一行可用,该行将始终为您提供空值。 正确的方法应该是:
UPDATE table1 f1
SET f1.operations_yesterday =
(WITH table1_lag AS (SELECT ff.YEAR,
ff.MONTH,
ff.DAY,
lag(ff.operations, 1, 0) over(ORDER BY ff.YEAR, ff.MONTH, ff.DAY) AS yesterday
FROM table1 ff)
SELECT f2.yesterday
FROM table1_lag f2
WHERE f1.year = f2.year
AND f1.month = f2.month
AND f1.day = f2.day);
不建议冗余存储数据。 但是...
您想在记录中存储前一天的数据。 您假设每天都有一条记录,因此前一天也将是按日期排序之前的记录 。 但是这些知识并没有真正的帮助,因为选择前一天比记录之前更容易。
分别存储日期,月份和年份而不是仅仅存储日期是很奇怪的。 我不知道您要达到什么目的。 我们将不得不笨拙地进行转换。
update table1 today
set operations_yesterday =
(
select operations
from table1 yesterday
where to_date(yesterday.year * 10000 + yesterday.month * 100 + yesterday.day, 'yyyymmdd')
= to_date(today.year * 10000 + today.month * 100 + today.day, 'yyyymmdd') - 1
);
如果您存储日期,那将是简单的:
update table1 today
set operations_yesterday =
(select operations from table1 yesterday where yesterday.date = today.date - 1);
如果想要0而不是null(昨天没有),则添加COALESCE
(或Oracle的NVL
)。
如果缺少日期,并且您希望从前一天的值开始,那么可以使用merge
:
merge into table1 t1
using (select lag(operations, 1, 0)
over (partition by id_office order by year, month, day) lop
from table1 t) t2
on (t1.rowid = t2.rowid)
when matched then update set operations_yesterday = t2.lop;
测试数据:
create table table1(Year number(4), Month number(2), Day number(2),
ID_Office number(5), Operations number(4), Operations_yesterday number(4));
insert into table1 values (2016, 12, 31, 9555, 500, null);
insert into table1 values (2017, 1, 1, 9555, 600, null);
insert into table1 values (2017, 1, 2, 9555, 750, null);
insert into table1 values (2017, 1, 3, 9556, 800, null);
insert into table1 values (2017, 1, 5, 9556, 400, null);
...并merge
后:
select * from table1;
YEAR MONTH DAY ID_OFFICE OPERATIONS OPERATIONS_YESTERDAY
----- ----- --- --------- ---------- --------------------
2016 12 31 9555 500 0
2017 1 1 9555 600 500
2017 1 2 9555 750 600
2017 1 3 9556 800 0
2017 1 5 9556 400 800
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.