更新PostgreSQL上所有受影响行的顺序

cwxwcias  于 5个月前  发布在  PostgreSQL
关注(0)|答案(4)|浏览(63)

我有下面这个表的简化版本,每一行都有一个item_order值,由它的parent_id分区。
| 项目ID|项目名称|父ID|项目顺序|
| --|--|--|--|
| 523 |鱼| 1 | 1 |
| 562 |蜗杆| 1 | 2 |
| 612 |小鼠| 1 | 3 |
| 251 |奶酪| 1 | 4 |
| 723 |番茄酱| 2 | 1 |
| 912 |意大利面| 2 | 2 |
| 52 |芯片| 2 | 3 |
假设我想将'mice'的'item_order'值设置为1。

UPDATE
    my_table 
SET
    item_order = 1
    WHERE item_id = 612;

字符串
我需要的表更新如下。(预期的变化突出显示。)
| 项目ID|项目名称|父ID|项目顺序|
| --|--|--|--|
| 612 |小鼠| 1 |3 →1|
| 523 |鱼| 1 |1 → 2**|
| 562 |蜗杆| 1 |2 →3|
| 251 |奶酪| 1 | 4 |
| 723 |番茄酱| 2 | 1 |
| 912 |意大利面| 2 | 2 |
| 52 |芯片| 2 | 3 |
如何更新同一parent_id中所有受影响行的item_order值?

4urapxun

4urapxun1#

你可以通过一个更新来实现这一点,该更新从你想要移动的item_id中获取item_order。
只有那些在更改后的订单之下的订单也需要移动。

UPDATE my_table t
SET item_order =
     case 
     when t.item_order = t2.item_order then 1
     when t.item_order < t2.item_order then t.item_order + 1
     else t.item_order
     end
FROM my_table t2
WHERE t.parent_id = t2.parent_id
  AND t.item_order <= t2.item_order
  AND t2.item_id = 612;
3 rows affected
select *
from my_table
order by parent_id, item_order

| 项目ID|项目名称|父ID|项目顺序|
| --|--|--|--|
| 612 |小鼠| 1 | 1 |
| 523 |鱼| 1 | 2 |
| 562 |蜗杆| 1 | 3 |
| 251 |奶酪| 1 | 4 |
| 723 |番茄酱| 2 | 1 |
| 912 |意大利面| 2 | 2 |
| 52 |芯片| 2 | 3 |
关于 *db<>fiddle here * 的演示

huus2vyu

huus2vyu2#

找到item_id = 1parent_id记录,然后更新parent_id等于parent_id的所有记录。

UPDATE my_table 
SET
   item_order = 1
WHERE parent_id = (SELECT parent_id FROM my_table WHERE item_id = 1);

字符串

1mrurvl1

1mrurvl13#

您想在排序列表中移动一个项目。为此,您必须将项目的排序关键字更改为新位置,并将该位置的所有现有排序关键字增加一个。

set @item_id = 612;
set @item_order = 1;

UPDATE my_table 
SET item_order =
   case when item_id = @item_id then @item_order
        when item_order >= @item_order then item_order + 1
        else item_order
   end
WHERE parent_id = (SELECT parent_id FROM my_table WHERE item_id = @item_id);

字符串

mjqavswn

mjqavswn4#

我最终通过对item_order列使用小数来解决这个问题。
如果您尝试将612的item_order设置为1,则将其新的item_order值递减一个伪浮点数。

UPDATE
    my_table 
SET
    item_order = 1 - 0.1
    WHERE item_id = 612;

字符串
现在表格看起来像这样:
| 项目ID|项目名称|父ID|项目顺序|
| --|--|--|--|
| 612 |小鼠| 1 |0.9|
| 523 |鱼| 1 | 1 |
| 562 |蜗杆| 1 | 2 |
| 251 |奶酪| 1 | 4 |
| 723 |番茄酱| 2 | 1 |
| 912 |意大利面| 2 | 2 |
| 52 |芯片| 2 | 3 |
然后检查具有相同parent_id的行,并将它们的item_order设置为row_number()函数的值。

UPDATE 
    my_table
SET
    item_order = T2.row_number
FROM 
    (SELECT item_id, item_order, row_number()
        OVER (ORDER BY item_order)
        FROM my_table
        WHERE parent_id = (SELECT parent_id FROM my_table WHERE item_id = 612))
    AS T2
WHERE T2.item_id = my_table.item_id;


结果如下:
| 项目ID|项目名称|父ID|项目顺序|
| --|--|--|--|
| 612 |小鼠| 1 | 1 |
| 523 |鱼| 1 | 2 |
| 562 |蜗杆| 1 | 3 |
| 251 |奶酪| 1 | 4 |
| 723 |番茄酱| 2 | 1 |
| 912 |意大利面| 2 | 2 |
| 52 |芯片| 2 | 3 |
上面的例子只在给定值之前插入。为了在给定值之后插入,必须将伪浮点数添加到item_order中。另一个问题是,同一父ID内的所有行都被更新,而不管它们是否需要更新。
db<>fiddle

相关问题