DB2 根据另一列中的不同值更新具有递增数字的列

Posted

技术标签:

【中文标题】DB2 根据另一列中的不同值更新具有递增数字的列【英文标题】:DB2 update column with incrementing number based on distinct values in another column 【发布时间】:2016-02-18 09:32:35 【问题描述】:

对于每个不同的 ref_no 值,我想使用从 1 开始的递增值的运行序列来更新 seq_no 列。

REF_NO  SEQ_NO (initial)    SEQ_NO (expected)
------- -------             -------
   111.      -                   1.
   111.      -                   2.
   111.      -                   3.
   222.      -                   1.
   222.      -                   2.
   333.      -                   1.
   100.      -                   1.
   100.      -                   2.
   100.      -                   3.
   100.      -                   4.
     0.      -                   1.
   333.      -                   2.
   100.      -                   5.
   200.      -                   1.

我只能通过重复多个语句来做到这一点:

declare x1 cursor for select * from xyz where seq_no is null for update of seq_no
open x1

fetch from x1
update xyz a set a.seq_no = (select nvl(max(b.seq_no)+1, 1) from xyz b where b.ref_no = a.ref_no) where current of x1
  -- REPEAT ABOVE TWO STATEMENTS UNTIL FETCH RETURNS NO ROW --

close x1
select * from xyz

是否可以完全使用单个 UPDATE 语句来完成此操作,只运行一次以更新整个表?数据库是 IBM DB2。

注意:不同 ref_no 的行的实际顺序是任意的,并不重要。

【问题讨论】:

【参考方案1】:

使用Row_Number窗口函数

select row_number()over(partition by REF_NO  order by REF_NO) as seq_no
from yourtable

要更新表格试试这个

MERGE INTO xyz A
USING (SELECT rowid row_id,
              Row_number()
                OVER(
                  partition BY ref_no
                  ORDER BY ref_no ) as seq_no
       FROM   xyz) B
ON A.rowid = B.row_id
WHEN MATCHED THEN
  UPDATE SET A.seq_no = B.seq_no 

【讨论】:

好的,这显示了我预期的值,但是我如何用它们更新seq_no 列?我需要保存它们。 @ADTC 行相同吗?或者它们之间是否存在一些不同的值,以便我们识别它们 没有其他列,所以行确实相同。但是,有一个名为rowid系统列 似乎可以区分每一行。我试图用它来做更新,但语句失败:update xyz A set A.seq_no = (select B.seq_no from (select rowid row_id, row_number() over(partition by ref_no order by ref_no) as seq_no from xyz) B where A.rowid = B.row_id) @ADTC - 请注意,rowid 在面临重组和其他一些事情时并不稳定。 @Clockwork-Muse 我认为如果您只是在MERGE 语句执行期间临时使用它,而不是将其存储在任何地方以供以后调用,就可以了。只要我确定数据库在执行期间没有做任何重组或其他事情。对吗?【参考方案2】:

如果您没有表主键,您可以使用Relative Record Number SQL Function 和下面的查询来更新您的结果:

MERGE INTO
    ref AS r
USING
    (
        SELECT
            RRN(ref) AS rrn,
            ROW_NUMBER() OVER(PARTITION BY ref_no ORDER BY RRN(ref)) AS seq_no
        FROM
            ref
    ) AS n
ON
    RRN(r) = n.rrn
WHEN MATCHED THEN
    UPDATE SET
        seq_no = n.seq_no;

通常,在您的表上没有主键列是一个坏主意。考虑添加标识列。可以在已经存在的表上完成:

ALTER TABLE ref ADD COLUMN id INTEGER NOT NULL DEFAULT 0;
ALTER TABLE ref ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY;

【讨论】:

以上是关于DB2 根据另一列中的不同值更新具有递增数字的列的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历一张表中的列值并将另一列中的 COUNTIF 值粘贴到另一张表中

PSQL - 查找所有值并根据另一列中的非唯一值使其唯一

根据另一列中的值更新 BigQuery 中的嵌套数组

从不同表的另一列中的一列中查找所有值

TSQL - 如何在另一列中提取具有最小值和最大值的列

在 SQL 中,我可以在另一列中获取与它们没有关联的特定值的列中的值吗?