SQL递归查询Postgres

时间:2017-03-16 01:41:23

标签: sql postgresql recursive-query

所以我有一个表companyinfo,其数据如下:

company |    role      |    person
--------|--------------|------------
Google  | dev          | John
Google  | tester       | Bob
Facebook| manager      | Alex
Facebook| blah         | Bob

我想找到多少"连接"约翰认识人吗?因此,如果约翰和鲍勃在谷歌工作约翰通过1连接知道鲍勃,但如果约翰知道鲍勃和鲍勃知道亚历克斯比约翰也知道亚历克斯扩展,但通过鲍勃意味着2连接

我理解这是在代码中解决的非常简单的图形问题,但我一直在试图弄清楚如何编写递归sql来执行这几个小时并且只提出:

WITH RECURSIVE search_graph(person, company, n) AS (
    SELECT s.person, s.company, 1
    FROM companyinfo s
    WHERE s.person = 'John'
  UNION
    SELECT s.person, s.company, n+1 
    FROM companyinfo s, search_graph sg
    WHERE s.person = 'Alex'
)
SELECT * FROM search_graph limit 50;

但它显然不起作用,是的它确实找到了Alex,但不是因为通过bob和循环不忠而跟随连接因此limit 50

澄清: 如果两个人在同一家公司工作,我们假设他们互相认识。所以图表看起来像这样:

|约翰| --dev-- |谷歌| --tester-- |鲍勃| --blah-- | Facebook的|

这样人们和公司就是节点,角色就是边缘。

1 个答案:

答案 0 :(得分:1)

基本查询找到在同一家公司工作的人与某个人在SQL中转换为companyinfo的自联接。此外,应该使用一系列人来消除重复。

with recursive search_graph(person, persons) as (
    select s2.person, array['John']
    from companyinfo s1
    join companyinfo s2 
    on s1.company = s2.company and s1.person <> s2.person
    where s1.person = 'John'
union
    select s2.person, persons || s1.person
    from companyinfo s1 
    join companyinfo s2 
    on s1.company = s2.company and s1.person <> s2.person
    join search_graph g 
    on s1.person = g.person
    where s1.person <> all(persons)
)
select distinct persons[cardinality(persons)] person, cardinality(persons) n
from search_graph
order by 2;

 person | n 
--------+---
 John   | 1
 Bob    | 2
 Alex   | 3
(3 rows)