基于其他两列并使用 LAG 函数更新 Oracle 过程中的列

Posted

技术标签:

【中文标题】基于其他两列并使用 LAG 函数更新 Oracle 过程中的列【英文标题】:Updating a column in an Oracle procedure based on other two columns and using a LAG function 【发布时间】:2017-03-09 16:50:25 【问题描述】:

我正在尝试使用以下过程更新列,它使用 LAG 函数,因为结果是通过将前一个值减去当前值来计算的,如下图所示,但它没有只要它用我完全不期望的值填充 col3 就可以工作..

基本上我想要的是(用Excel来说明问题):

我希望表中每个不同的名字都有这个。

create or replace procedure proc1 as
  cursor cur is
    SELECT (col1 - LAG(col1,1) OVER (PARTITION BY name order by ID)) 
    FROM table1 
    for update;
    var_diff NUMBER;
begin
  open cur;
  loop
    fetch cur into var_diff;
    exit when cur%NOTFOUND;
    update table1 set col3=var_diff where current of cur;
  end loop;
  close cur;
end proc1;
/

exec proc1;
commit;

例如,我知道上面使用的 SQL 语句有效:

SELECT col1, 
       LAG(col1,1) OVER (PARTITION BY name order by ID), 
       (col1 - LAG(col1,1) OVER (PARTITION BY name order by ID)) 
FROM table1;

但我无法使程序正常工作。

【问题讨论】:

c_f; 的当前位置在哪里?为什么你使用 c_f?不应该是你的光标名吗? 我已经测试了你的代码。除了窗口第一行中的col3 为空而不是col1 的当前值之外,它会生成Excel 屏幕截图中显示的结果。这很容易用nvl() 或其他东西解决。如果您认为您的问题比您需要发布的完整(但很小)可重现的测试用例更广泛。 您可以在 proc 中逐行更新表,但这是一个缓慢的选择。有人说,逐行 = 慢慢来。您可以完全在 SQL 中完成此操作。您可能正在测试/尝试学习 pl/sql,这很好,只要明白这不是做您正在做的事情的最佳方式。 c_f 是拼写错误,应该是 cur。已编辑,但仍无法正常工作。 【参考方案1】:

我觉得这可以仅通过 SQL 轻松完成。如果可能,我们应该/必须始终尝试通过 SQL 方法解决问题,然后在需要时寻找 PLSQL 选项。这个要求可以通过 MERGE 或简单的 UPDATE 语句轻松完成。我已经说明了两种 PLSQL ND sql 方式。希望这会有所帮助。

--SQL Way better then PLSQL way
merge INTO TABLE1 tab USING
(SELECT (COL1 - LAG(COL1,1) over (partition BY name order by id)) COL1
FROM TABLE1
)a ON (TAB.COL1 = a.COL1)
WHEN matched THEN
  UPDATE SET COL3 = a.COL1 WHERE col1 = a.col1;

--PLSQL way but will be slow as we are doing it row-row aka slow-by-slow provcessing
CREATE OR REPLACE
PROCEDURE proc1
AS
BEGIN
  for I        in
  (SELECT (COL1 - LAG(COL1,1) over (partition BY name order by id)) col3,col1
  FROM table1
  )
  LOOP
    UPDATE table1 SET col3=i.col3 where col1 = i.col1;
  END LOOP;
END proc1;

【讨论】:

看看你的对我有用,但我必须做一些调整。见下文。【参考方案2】:

最后,按照别人的建议,这个SQL语句对我有用:

MERGE INTO TABLE1 tab 
    USING (SELECT ID,(NVL(COL1,0) - NVL(LAG(NVL(COL1,0),1) OVER (PARTITION BY NAME order by ID),0)) VAL FROM TABLE1) a 
    ON (tab.ID = a.ID)
    WHEN matched THEN
      UPDATE SET tab.COL3 = a.VAL;

【讨论】:

以上是关于基于其他两列并使用 LAG 函数更新 Oracle 过程中的列的主要内容,如果未能解决你的问题,请参考以下文章

SQL-Oracle 使用 LAG() 从自身更新表

MYSQL lag() 和lead()函数使用介绍

Oracle 中的 LAG 函数

Oracle分析函数之Lag和Lead()使用

Oracle SQL LAG 函数

ORACLE 偏移分析函数 lag()与lead() 用法