使用LAG()

时间:2017-09-15 09:07:01

标签: sql oracle sql-update

让我们假设我们有一个像这样的表:

| 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语句解决方案。

注意: 请注意,可以按顺序排列三个以上的字段。我只将年份,月份和日期作为示例,但还有更多与日期无关的字段。 此外,重要的是要详细说明并非每天都有价值观。

提前谢谢!

3 个答案:

答案 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