如何 select 一系列链接行中的最后一行

How to select last row from a series of linked rows

我要解决的问题是 HTTP 重定向。每次用户更改文章标题时,都会创建一个新的 URL,但旧的 URL 仍应指向最新的文章。

可以多次更改文章标题,因此跟踪名称更改的 table 有一对新旧 URL。

示例:

orange -> pear
pear -> apple
apple -> grape

table 看起来像这样:

                   Table "public.redirects"
  Column  |           Type           |       Modifiers
----------+--------------------------+------------------------
 from_url | character varying(200)   | not null
 to_url   | character varying(200)   | not null
 code     | smallint                 | not null default 301
 added    | timestamp with time zone | not null default now()
Indexes:
    "redirects_pkey" PRIMARY KEY, btree (from)

我在插入期间处理无限循环,但我遇到的问题是如何 select 最后一个 URL 以避免发出多个重定向。

如果请求是针对 "orange",则使用上面的示例,我想直接发出重定向到 "grape"。这可以在单个 select 查询中实现吗?

为此你需要 recursive query

with recursive all_redirects as 
(
   select from_url, 
          to_url, 
          1 as level
   from redirects
   where from_url = 'orange'

   union all

   select c.from_url,
          c.to_url,
          p.level + 1
   from redirects c
     join all_redirects p on p.to_url = c.from_url
)
select to_url
from all_redirects
order by level desc
limit 1;

SQLFiddle: http://sqlfiddle.com/#!15/358a7/1

查询将受益于 (from_url, to_url) 上的索引。如果需要,查询也可以处理无限循环。