Oracle—基于上一行值更新连续行的最快方法

Oracle—基于上一行值更新连续行的最快方法,oracle,plsql,sql-update,Oracle,Plsql,Sql Update,我有一个包含数量和剩余列的表,在对某个日期列进行排序后,必须更新表中的所有行 剩余列的值由(上一行的剩余)+或-(此行的数量)计算。我已经编写了一个游标循环来完成这项任务,但它需要很长时间才能完成 OPEN KAL; LOOP FETCH KAL INTO V_PK_ID, V_TYPE_ID, V_QUANTITY; IF (V_TYPE_ID = 1) THEN V_REMAINING := V_REMAI

我有一个包含数量和剩余列的表,在对某个日期列进行排序后,必须更新表中的所有行

剩余列的值由(上一行的剩余)+或-(此行的数量)计算。我已经编写了一个游标循环来完成这项任务,但它需要很长时间才能完成

OPEN KAL;
      LOOP
        FETCH KAL
          INTO V_PK_ID, V_TYPE_ID, V_QUANTITY;

        IF (V_TYPE_ID = 1) THEN
          V_REMAINING := V_REMAINING + V_QUANTITY;
        ELSE
          V_REMAINING := V_REMAINING - V_QUANTITY;
        END IF;

        UPDATE TABLE K
           SET K.REMAINING = V_REMAINING
         WHERE K.KALAMAZOO_ID = V_PK_ID;

      END LOOP;
CLOSE KAL;
我可以做些什么来更快地实现这一点,或者我可以使用其他方法来实现这一点吗

编辑:样本数据

PK  TYPE    QUANTITY    REMAINING
1   1       100         900
2   2       50          950
3   2       25          975
4   1       200         775
5   1       125         650
6   1       50          600

例如,如果我以“1000”开头,则类型1表示(-),类型2表示(+),行将按上述方式更新。

您可以使用
合并
来完成此操作。逻辑是这样的:

merge into k
      using (select k.*,
                    sum(case when v_type_id = 1 then v_quantity else - v_quantity end) over
                        (order by v_pk_id) as new_remaining
             from k
            ) s
      on (k.v_pk_id = s.v_pk_id)
when matched then
    update set k.remaining = s.new_remaining;

计算不需要PL/SQL循环。

您可以使用
merge
进行此操作。逻辑是这样的:

merge into k
      using (select k.*,
                    sum(case when v_type_id = 1 then v_quantity else - v_quantity end) over
                        (order by v_pk_id) as new_remaining
             from k
            ) s
      on (k.v_pk_id = s.v_pk_id)
when matched then
    update set k.remaining = s.new_remaining;

计算不需要PL/SQL循环。

请显示示例表数据并查询表中显示的1000是什么?或者它是以其他方式输入的?同样,这是您的基表结构,还是您正在为视图执行此操作?如果是基表,
剩余的
应该是一个虚拟列()-将其保存为存储列将违反基本规范化原则。@它不能是虚拟的,因为它不是从同一行派生的。如果您长期从事数据库编程,您现在会发现“违反基本规范化原则”不是违反。有时候你需要去规范化。@motor-ugh,关于虚拟列的事情,你是对的,没有直接思考。我理解需要反规范化的观点,但当数据不是正常形式时,通常是没有理由的。至于长期从事数据库编程,我从其他行业退休(很早),对数据库编程感兴趣,只是为了志愿工作;我只是在今年二月第一次写了一条SQL语句。。。我只是想澄清一下我是从哪里来的,并解释一下我犯的许多新手错误。谢谢请显示样本表数据并查询表中显示的1000是多少?或者它是以其他方式输入的?同样,这是您的基表结构,还是您正在为视图执行此操作?如果是基表,
剩余的
应该是一个虚拟列()-将其保存为存储列将违反基本规范化原则。@它不能是虚拟的,因为它不是从同一行派生的。如果您长期从事数据库编程,您现在会发现“违反基本规范化原则”不是违反。有时候你需要去规范化。@motor-ugh,关于虚拟列的事情,你是对的,没有直接思考。我理解需要反规范化的观点,但当数据不是正常形式时,通常是没有理由的。至于长期从事数据库编程,我从其他行业退休(很早),对数据库编程感兴趣,只是为了志愿工作;我只是在今年二月第一次写了一条SQL语句。。。我只是想澄清一下我是从哪里来的,并解释一下我犯的许多新手错误。谢谢@摩托。我没有拒绝对这个答案进行任何编辑。@Motor。谢谢你。@motor。我没有拒绝对这个答案进行任何编辑。@Motor。非常感谢。