2017-03-16 176 views
0

所以我有了像這樣的數據表公司信息:SQL遞歸查詢的Postgres

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

我想找到通過多少個「連接」 John知道的人。因此,如果約翰和鮑勃在谷歌工作約翰知道鮑勃通過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; 

但它顯然是行不通的,是的,它確實找到亞歷克斯,但不是因爲以下通過鮑勃連接和循環不忠,因此limit 50

澄清: 如果兩個人在同一家公司工作,我們假設他們彼此瞭解。因此,該圖看起來像這樣:

| John | --dev-- | Google | --tester-- | Bob | --blah-- | Facebook |

這樣的人和公司是節點和角色的邊緣。

+0

您的表'companyinfo'沒有任何關於人與人之間關係的信息。 –

+0

我應該澄清 - 在同一家公司工作過的人都認識對方 – polyx

回答

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)  
+0

太棒了,但是'2 by order by'做什麼? – polyx

+1

與'order by n'一樣(按第二列排序)。 – klin