【问题标题】:How modify sequence numbers based on one changed sequence number in oracle sqloracle sql中如何根据一个更改的序列号修改序列号
【发布时间】:2022-01-15 13:47:15
【问题描述】:

当一个序号改变时,如何改变其余序号。然后根据序列号对行进行排序。示例如下:

  seq_nbr
A 1        |   A 1       |  A 1
B 2 -> 5   |   B 5       |  C 2
C 3        |   C 3 -> 2  |  D 3
D 4        |   D 4 -> 3  |  E 4
E 5        |   E 5 -> 4  |  B 5

【问题讨论】:

  • 如果将 5 更改为 1,您期望什么?
  • @SayanMalakshinov,如果那样,结果将是 A2、B3、C4、D5
  • 我的意思是 B = 1。如果将 B 更改为 1 会怎样?你将如何确定哪一个发生了变化?
  • @SayanMalakshinov,我在你的上一个问题中没有正确回答。如果将 B 更改为 1,则答案将是 B1、A2、C3、D4、E5。它基于序列号。如果更改为较小的序号,则与新序号相比,序号较大的项目应相应更改。如果改成较大的序号,则序号较小的项也应相应更改。

标签: sql oracle


【解决方案1】:

当分配给 B 的新序号大于旧序号时,将旧值和新值之间的序号下推(减 1),以保持该列中的连续编号。

Sayan M 在评论中问您,如果您将序列号更改为 较低 值而不是较高值,期望的结果是什么。大概在这种情况下,旧值和新值之间的所有序列号都必须向上推(加 1),以保持连续编号。

下面的update 语句解决了这两种情况(以及序列号不改变的简单情况 - 它已更新为自身)。它不需要分析函数,它作为update 语句工作。

我假设与 MT0 的答案相同的表名和列名,输入是“值”和“新序号”(例如“B”和“5”) - 作为绑定变量给出。

update 
  (
    select value, seq_nbr,
           (select seq_nbr from table_name where value = :i_value) as old_nbr
    from   table_name
  )
  set seq_nbr = 
    case when value = :i_value then :i_nbr
         else seq_nbr + case when :i_nbr > old_nbr then -1 else 1 end
    end
  where :i_nbr != old_nbr 
    and seq_nbr between least(:i_nbr, old_nbr) and greatest(:i_nbr, old_nbr)
;

【讨论】:

    【解决方案2】:

    您可以将MERGE 语句与ROW_NUMBER 分析函数一起使用:

    MERGE INTO table_name dst
    USING (
      WITH new_seq_nbr (value, new_nbr) AS (
        SELECT 'B', 5 FROM DUAL                       -- Your change goes here.
      )
      SELECT t.ROWID AS rid,
             ROW_NUMBER() OVER (
               ORDER BY
                 CASE t.value
                 WHEN n.value
                 THEN 2 * new_nbr + 1
                 ELSE 2 * seq_nbr
                 END
             ) AS new_seq_nbr
      FROM   table_name t
             CROSS JOIN new_seq_nbr n
    ) src
    ON (src.rid = dst.ROWID)
    WHEN MATCHED THEN
      UPDATE
      SET dst.seq_nbr = src.new_seq_nbr
      WHERE dst.seq_nbr <> src.new_seq_nbr;
    

    其中,对于样本数据:

    CREATE TABLE table_name (value PRIMARY KEY, seq_nbr UNIQUE) AS
    SELECT 'A', 1 FROM DUAL UNION ALL
    SELECT 'B', 2 FROM DUAL UNION ALL
    SELECT 'C', 3 FROM DUAL UNION ALL
    SELECT 'D', 4 FROM DUAL UNION ALL
    SELECT 'E', 5 FROM DUAL UNION ALL
    SELECT 'F', 6 FROM DUAL;
    

    然后MERGE 然后:

    SELECT * FROM table_name ORDER BY seq_nbr;
    

    输出:

    VALUE SEQ_NBR
    A 1
    C 2
    D 3
    E 4
    B 5
    F 6

    db小提琴here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多