简体   繁体   English

在PL / SQL中,如何根据下一行更新一行?

[英]In PL/SQL, how do you update a row based on the next row?

I'm using Oracle PL/SQL. 我正在使用Oracle PL / SQL。

I have a timestamped table T, and I want to set a row's value for column A to be the same as that of the previous row, if they're sorted by columns B and Timestamp, provided that the timestamps are not different by more than 45 seconds. 我有一个带时间戳的表T,并且我想将A列的行值设置为与上一行的值相同(如果它们按B列和Timestamp排序),条件是时间戳记相差不超过45秒。

In pseudocode, it's something like: 在伪代码中,它类似于:

UPDATE T t_curr
  SET A =
    (SELECT A
      FROM T t_prev
      INNER JOIN t_curr
        ON (t_prev is the row right before t_curr, when you sort by B and Timestamp)
          AND t_curr.Timestamp - t_prev.Timestamp < 45
    )

I tried this: 我尝试了这个:

UPDATE T t_curr
  SET A =
    (SELECT A
      FROM T t_prev
      INNER JOIN t_curr
        ON RANK (t_curr)
          OVER (B, Timestamp)
          = 1 + RANK (t_prev)
          OVER (B, Timestmap)
          AND t_curr.Timestamp - t_prev.Timestamp < 45
    )

But I got: 但是我得到了:

Error(38,16): PL/SQL: ORA-00934: group function is not allowed here 错误(38,16):PL / SQL:ORA-00934:此处不允许使用组功能

pointing at the first instance of RANK. 指向RANK的第一个实例。

What did I do wrong, and how do I get this right? 我做错了什么,我该怎么做呢?

Try using a merge statement. 尝试使用合并语句。 Not sure it quite does what you want but it should work. 不确定它是否完全符合您的要求,但它是否可以正常工作。 Unfortunately the insert clause is necessary) but shouldn't ever be called. 不幸的是,insert子句是必需的),但永远不要调用它。

merge into t a
using (
  select 
    A, 
    B, 
    timestamp, 
    lag(A) over (order by id, timestamp) as prior_A,
    lag(timestamp) over (order by B, timestamp) as prior_timestamp
  from t) b
on  (a.B = b.B)
when matched then 
  update set a.a = case when b.timestamp-b.prior_timestamp <= 45 
    then b.prior_A else b.A end
when not matched then insert (B) values (null)

Can you try something like this: 你可以尝试这样的事情:

update x 
set x = y.A
from T x
join T y
where x.B = (select MAX(B) from T where B < y.B)
and x.Timestamp = (select MAX(Timestamp) from T where Timestamp < y.Timestamp)
and y.Timestamp - x.Timestamp < 45

And another option... doesn't quite do what do want because it ignores the requirement to sort on B but it might give you something to think about.... Without table definitions and things it was a little hard to get a handle on exactly what was required. 还有另一种选择...并没有完全按照需要做,因为它忽略了对B进行排序的要求,但是它可能会给您一些思考...。如果没有表定义和其他东西,那么很难获得一个句柄完全符合要求。

Edit: on reading the question again, it looks like your syntax is wrong. 编辑:再次阅读问题时,您的语法似乎错误。 Group functions (lead/lag/rank etc) can only appear in the select list or the order by clause. 组功能(超前/滞后/等级等)只能出现在选择列表或order by子句中。 They are evaluated after the joins, where, group by and having clauses. 它们在连接,where,group by和having子句之后进行评估。 So something like what is shown below should work. 因此,如下所示的内容应该可以工作。

update T a
set A = (select 
  new_A
  from (
  select 
    B, 
    A, 
    timestamp, 
    first_value(A) 
      over (order by timestamp range between 45 preceding and current row) as new_A
  from mike_temp_1
) b where b.id = a.id)

What you can do is. 你能做的是。

update t
set colToUpdate = nextValue
from  (
select A
      ,B
      ,C
      ,(LEAD(B, 1, null) over (order by A)) as nextValue
  FROM db.schema.table
  ) as t
    where colToUpdate is null

This requires that the column you want to update is null, unless you want to update all of them. 这要求您要更新的列为空,除非您要更新所有列。

You could try (might need some tweaking to get it right, but the idea is two identical ordered subqueries joined by offset rownumbers) 您可以尝试(可能需要进行一些调整才能使其正确执行,但想法是两个相同的有序子查询,并由偏移行号连接在一起)

update T set a = (select A1
                 from (
                       select S1.A A1, rownum r1
                       from (select * from T order by B, timestamp) S1
                       left outer join
                       select S2.A A2, rownum r2
                       from (select * from T order by B, timestamp) S2
                       on r1 = r2-1
                      )
                  )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM