让我们假设我们有一个像这样的表:
| 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);
你能否从我的代码中给我一些关于错误的建议? 我在“Insert Into”语句中成功使用了lag()函数,但在这种情况下,我必须提供一个Update语句解决方案。
注意: 请注意,可以按顺序排列三个以上的字段。我只将年份,月份和日期作为示例,但还有更多与日期无关的字段。 此外,重要的是要详细说明并非每天都有价值观。
提前谢谢!
答案 0 :(得分:2)
只要在子查询中传递年,月和日的值,就只有一行可用于滞后函数,它始终会为您提供空值。正确的方法应该是:
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);
答案 1 :(得分:2)
不建议冗余存储数据。但是......
您希望在记录中存储前一天的数据。您认为每天都有一条记录,因此之前也将是按日期排序之前的记录。但是这种知识并没有真正帮助,因为前一天的选择比以前的记录更容易。
分别存储日,月和年而不仅仅是日期是非常奇怪的。我不知道你想用这个来实现什么。我们必须笨拙地转换它。
var arr = [{ "name": "Port 01", "portsActual": [ "Hong Kong", "Ningbo, CN", "Hong Kong", ] }, { "name": "Port 02", "portsActual": [ "Kobe, JP", "Osaka, JP", "Osaka, JP" ] } ]
arr.forEach(a => {
a.portsActual = a.portsActual.filter((i, k) => a.portsActual.indexOf(i) == k)
})
console.log(arr)
如果您存储日期而不是简单地:
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);
(或Oracle的COALESCE
),如果你想要0而不是null,那就没有昨天。
答案 2 :(得分:0)
如果在这种情况下缺少日期且你想要前天的价值,那么你可以使用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