用于查找喜欢层次结构的递归SQL(具有潜在的圆圈)

时间:2011-12-05 16:05:31

标签: sql postgresql recursion hierarchy

我有一个喜欢的表(uid1喜欢uid2)并且给定了特定的用户ID(uid)我需要找到喜欢他的所有人,或者喜欢他的人,依此类推。

with recursive Hierarchy(uid, Level)
as
(
    select 
        uid1 as uid, 1 as Level
   from 
    Likes l
   where 
    l.uid2 = 1 --parameter will go here
    union all
    select  
        l.uid1, lh.Level + 1
    from 
        Likes l   
    inner join Hierarchy lh
        on l.uid2 = lh.uid
    where l.uid1 not in (select uid from Hierarchy) --this is wrong syntax in postgresql
)

select * from Hierarchy

例如,在表Likes中给出以下值时会出现问题

2,1 (2 likes 1)
3,1 (3 likes 1)
4,1 (4 likes 1, 1 is popular)
3,4 (3 likes 4)
4,3 (4 likes 3)

在喜欢的层次结构中有一个圆圈,我想只添加不是前一次迭代的项目(因此是NOT IN)。

那么是否可以仅插入限制以添加新的uid?

1 个答案:

答案 0 :(得分:1)

基于此模板:

WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS (
        SELECT g.id, g.link, g.data, 1,
          ARRAY[g.id],
          false
        FROM graph g
      UNION ALL
        SELECT g.id, g.link, g.data, sg.depth + 1,
          path || g.id,
          g.id = ANY(path)
        FROM graph g, search_graph sg
        WHERE g.id = sg.link AND NOT cycle
)
SELECT * FROM search_graph;

(http://www.postgresql.org/docs/8.4/static/queries-with.html)

你得到:

with recursive Hierarchy(uid, Level, path, cycle)
as
(
    select 
        uid1 as uid, 1 as Level, ARRAY[l.uid], false
   from 
    Likes l
   where 
    l.uid2 = 1 --parameter will go here
    union all
    select  
        l.uid1, lh.Level + 1, 
        path || l.uid,
        l.uid = ANY( path )
    from 
        Likes l   
    inner join Hierarchy lh
        on l.uid2 = lh.uid
)

select * from Hierarchy