基于排序列值链接SQL中的行

基于排序列值链接SQL中的行,sql,oracle,linked-list,ranking,Sql,Oracle,Linked List,Ranking,我有一个数据库表,其中包含捐赠者的“状态”列表。捐赠5000美元的人有一定的等级,10000美元、50000美元等也有相同的等级。为了方便各种查询,我希望每个状态点都指向下一个最高的状态(除非是最高的)。像这样: ID Amount Next ID 1 $5,000 2 2 $10,000 3 3 $50,000 Null 每当插入新行、更新查询期间编辑的金额列或删除行时,我希望使用触发器自动更新下一个ID列 我正在为Oracle 9i构建这个

我有一个数据库表,其中包含捐赠者的“状态”列表。捐赠5000美元的人有一定的等级,10000美元、50000美元等也有相同的等级。为了方便各种查询,我希望每个状态点都指向下一个最高的状态(除非是最高的)。像这样:

ID    Amount    Next ID
1     $5,000    2
2     $10,000   3
3     $50,000   Null
每当插入新行、更新查询期间编辑的金额列或删除行时,我希望使用触发器自动更新下一个ID列

我正在为Oracle 9i构建这个,所以制作一个触发器来进行更新是没有问题的——唯一的问题是,如何做

我一直在为这样一个概念而苦苦挣扎:通过选择来获取整个表,通过按数量排序,然后以某种方式使用它来进行更新。看起来这应该是可能的,但我还没弄明白

另外,我确信某种PL/SQL循环可能会实现这一点

有什么想法吗?

将金额作为主键

例如,表是空的。然后插入金额10k:

Amount    Next ID
$10,000   null
然后插入值5k:找到第一个大于5k的值,即10k,因此使用10k作为下一个值:

Amount    Next ID
$5,000    10,000
$10,000   null
Amount    Next ID
$5,000    10,000
$7,000    10,000
$10,000   null
接下来,插入值7k:找到第一个大于7k的值,即10k,因此使用10k作为下一个值:

Amount    Next ID
$5,000    10,000
$10,000   null
Amount    Next ID
$5,000    10,000
$7,000    10,000
$10,000   null
但现在需要调整5k的值:找到小于7k的最大值,并将下一个设置为7k:

Amount    Next ID
$5,000    7,000
$7,000    10,000
$10,000   null
因此,概括而言,算法应为:

对于插入的任何新值:

Amount    Next ID
$10,000   null
1-在表>插入值中查找最小值,并将插入值的下一个id设置为表中的最小值

2-查找表中的最大值<要插入的值,并将表中最大值的下一个id设置为要插入的值

删除行: 如果表格如下所示:

Amount    Next ID
$5,000    7,000
$7,000    10,000
$10,000   null
然后我们要删除7000行

1-获取要删除的行的下一个id。在这种情况下,它是10k

2-获取下一个id为7k的行。在本例中,该行是具有5k的行

3-将步骤2中的行设置为步骤1中的下一个id

Amount    Next ID
$5,000    10,000
$7,000    10,000
$10,000   null
4-删除包含7k的行:

Amount    Next ID
$5,000    10,000
$10,000   null

我确信Alexandre的方法会很好地工作,但我使用的是稍微不同的方法。我肯定它更贵,但我觉得用它更安全

在删除、插入或更新“金额”列后,此触发器将重新链接所有状态,在所有场景中使用相同的过程:

create or replace trigger next_id_trg
  after
    delete or
    insert or
    update of AMOUNT
    on STATUS
  begin
    update STATUS
    set
      (STATUS.NEXT_ID) =
      (
        select
          NR.NEXT_ID
        from (
          with SQ as
            (
              select
                ID,
                ROW_NUMBER() over(order by STATUS.AMOUNT) as "ROW_NUMBER"
              from STATUS
            )
          select
            SQ1.ID,
            SQ2.ID as "NEXT_ID"
          from SQ SQ1
          left join SQ SQ2 on SQ2.ROW_NUMBER = SQ1.ROW_NUMBER + 1
        ) NR
        where STATUS.ID = NR.ID
      )
  end;
/
基本要点是:

  • 使用另一个表中的值执行更新
  • 使用子查询
  • 在子查询中使用
    ROW\u NUMBER()
    函数
  • 使用“WITH”子句命名子查询
  • 使用行号列上的增量将子查询的结果连接到自身
  • 这是从我的实际代码中转述出来的,但我确实测试了它,它确实工作得很好。我确信,如果有大量的行,可能会有更严重的性能损失,因为您将筛选表中的每一行,而不仅仅是修改过的行,这是AlexandreSantos建议的。但是我的桌子上有几十个,所以没有问题


    坦率地说,这很有趣,通过这样做,我学到了更多关于PL/SQL的知识^_^

    如果两个人捐赠相同的金额会怎么样?@AlexandreSantos表中的金额是某个人的状态、等级,而不是捐赠数字。个人将根据他们捐款的金额分配这些等级。很好,但我意识到,删除也需要考虑在内。如果一个等级被删除怎么办?我想出了一种不同的方法,但你的可能更好认可的。