我有一个表,基本上是这样的:
id | redirectid | data
其中redirectid是一个id到另一行。 基本上,如果一旦被选中,而且它有一个redirectid,那么redirectid数据应该在它的地方使用。 可能有多个重定向至redirectid为NULL。 从本质上讲,这些重定向形成在表中的链接列表。 我想知道的是,给定一个ID,是否有可能建立一个SQL查询,将通过所有可能的重定向循环,并在“名单”的最后返回的ID?
这是使用PostgreSQL 8.3,我想竭尽所能对SQL查询(如果可能,而不是重复在我的代码)。
这是否与条款使用PostgreSQL支持递归查询? 如果是这样,这样的事情可能会奏效。 (如果你想有一个测试的答案,提供一些CREATE TABLE和INSERT语句在你的问题,你需要在插入样本数据的结果一起)。
with Links(id,link,data) as (
select
id, redirectid, data
from T
where redirectid is null
union all
select
id, redirectid, null
from T
where redirectid is not null
union all
select
Links.id,
T.redirectid,
case when T.redirectid is null then T.data else null end
from T
join Links
on Links.link = T.id
)
select id, data
from Links
where data is not null;
补充说明:
:(您可以自行基础上,与Expression实现递归我不知道顺序编程PostgreSQL的语法,所以这是一个位伪:
插入此查询到一个新表称为链接的结果:
select
id, redirectid as link, data, 0 as depth
from T
where redirectid is null
union all
select
id, redirectid, null, 0
from T
where redirectid is not null
同时宣布的整数::深度和其初始化为零。 然后重复以下直到它不再添加行链接。 那么链接将包含你的结果。
increment ::depth;
insert into Links
select
Links.id,
T.redirectid,
case when T.redirectid is null then T.data else null end,
depth + 1
from T join Links
on Links.link = T.id
where depth = ::depth-1;
end;
我认为这将是比任何光标更好的解决方案。 其实,我真的不能相信的游标会如何对这个问题非常有用的。
请注意,如果有任何周期(重定向是最终圆形的),这将不会终止。
我说你应该创建一个用户定义的函数在这个脉络:
create function FindLastId (ID as integer) returns integer as $$
declare newid integer;
declare primaryid integer;
declare continue boolean;
begin
set continue = true;
set primaryid = $1;
while (continue)
select into newid redirectid from table where id = :primaryid;
if newid is null then
set continue = false;
else
set primaryid = :newid;
end if;
end loop;
return primaryid;
end;
$$ language pgplsql;
我对Postgres的语法有点不稳,所以你可能有一些清理工作要做。 无论如何,你可以调用你的函数,如下所示:
select id, FindLastId(id) as EndId from table
在像这样的表:
id redirectid data
1 3 ab
2 null cd
3 2 ef
4 1 gh
5 null ij
这将返回:
id EndId
1 2
2 2
3 2
4 2
5 5
请注意,这将是明显地慢,但它应该让你的ID的很快的小结果在一个很好的索引表中设置。