【发布时间】:2020-07-29 23:14:04
【问题描述】:
我有一个这样的表,它代表一个链表。当comes_after 列是null 时,表示它是链表中的第一条记录。
id | comes_after
--------+------------
"one" | null
"two" | "one"
"three" | "two"
"four" | "three"
如何使用 SQL 或 PLPGSQL 编写函数来重新排序行?函数 function move_id_after (id_to_move string, after_id string) 有 2 个参数,id_to_move 是要移动到新位置的 id,after_id 是要移动该行的 id。如果after_id 为空,则表示将其移至列表的开头。
这是我的尝试,但它不起作用,而且似乎不是理想的方法。如示例案例所示,我还希望能够将一行移动到列表的开头或末尾,并处理不需要更改的情况。
create function move_id_after (id_to_move string, after_id string) language plpgsql as $$
declare
AFTER_id_to_move string;
AFTER_after_id string;
id_to_move_used_to_follow string;
begin
select id from mytable where comes_after = id_to_move into AFTER_id_to_move;
select id from mytable where comes_after = after_id into AFTER_after_id;
update mytable set comes_after = id_to_move where id = AFTER_after_id;
update mytable set comes_after = AFTER_after_id where id = id_to_move returning id into id_to_move_used_to_follow;
update mytable set comes_after = id_to_move_used_to_follow where id = id_to_move_after;
end $$;
下面是一些结果应该如何的例子。
将记录移动到另一个位置
select move_id_after("two", "three") 应该变成:
id | comes_after
--------+------------
"one" | null
"three" | "one"
"two" | "three"
"four" | "two"
将记录移动到它已经在的位置
select move_id_after("three", "two") 应该没有变化:
id | comes_after
--------+------------
"one" | null
"two" | "one"
"three" | "two"
"four" | "three"
将第一条记录移到最后一个位置
select move_id_after("one", "four") 应该变成:
id | comes_after
--------+------------
"two" | null
"three" | "two"
"four" | "three"
"one" | "four"
将最后一条记录移动到第一个位置
select move_id_after("four", null) 应该变成:
id | comes_after
--------+------------
"four" | null
"one" | "four"
"two" | "one"
"three" | "two"
【问题讨论】:
-
如果记录的状态依赖于其他记录,这通常是设计不良的标志。 [即使这个问题是关于tabbing order,也不清楚]
标签: sql postgresql linked-list plpgsql sql-function