2017-04-02 71 views
1

我有如下關係:Recusive SQL查詢

公司信息(公司,角色,員工)

我想要做的就是找到兩個員工之間的最短「路徑」。

我需要找到喬和彼得之間的距離。 喬是A公司的首席執行官,而一個名叫Alex的人是董事會成員。 Alex是B公司的首席執行官,彼得是B公司的副總裁。那麼,喬和彼得之間的距離將是2.如果喬和彼得在同一家公司擔任角色,那將是1.

我需要使用遞歸SQL來解決這個問題。到目前爲止,我已經提出了基本案例和最終選擇字符串,但是我不能在我的生活中找出遞歸部分。

WITH RECURSIVE shortest_path(c1,p1,c2,p2, path) AS (
    -- Basecase -- 
    SELECT c1.company, c1.person, c2.company, c2.person, array[c1.person, c2.person] 
    FROM CompanyInfo c1 
    INNER JOIN CompanyInfo c2 ON c1.company = c2.company 
    WHERE c1.person = 'Joe' 
    AND c1.person <> c2.person 
UNION ALL 
    -- Recursive -- 
    -- This is where I'm stuck. 
) 

SELECT p1, p2, array_length(path,1) -1 as distance 
FROM shortest_path 
WHERE p2 = 'Peter' 
ORDER BY distance 
LIMIT 1; 

樣本數據

CREATE TABLE CompanyInfo (
    company text, 
    role text, 
    employee text, 
    primary key (company, role, employee) 
); 

insert into CompanyInfo values('Company A', 'CEO', 'Joe'); 
insert into CompanyInfo values('Company A', 'Board member', 'Alex'); 
insert into CompanyInfo values('Company B', 'CEO', 'Alex'); 
insert into CompanyInfo values('Company B', 'Board member', 'Peter'); 

期望輸出

person 1 | person 2 | distance 
Joe  Peter  2 
+0

標記您正在使用的dbms。 (該代碼是產品特定的。) – jarlh

+0

剛剛添加了標籤@jarlh –

+1

太棒了,希望您現在能夠得到更好的關注! – jarlh

回答

1

試試這個。繼續運行,直到新員工可以添加到路徑中。

CREATE TABLE CompanyInfo (
    company text, 
    role text, 
    employee text, 
    primary key (company, role, employee) 
); 

insert into CompanyInfo values('Company A', 'CEO', 'Joe'); 
insert into CompanyInfo values('Company A', 'Board member', 'Alex'); 
insert into CompanyInfo values('Company B', 'CEO', 'Alex'); 
insert into CompanyInfo values('Company B', 'Board member', 'Peter'); 


WITH RECURSIVE shortest_path(c1,p1,c2,p2, path) AS (
    -- Basecase -- 
    SELECT c1.company, c1.employee, c2.company, c2.employee, array[c1.employee, c2.employee] 
    FROM CompanyInfo c1 
    JOIN CompanyInfo c2 ON c1.company = c2.company 
     AND c1.employee = 'Joe' 
     AND c1.employee <> c2.employee 
    UNION ALL 
    -- Recursive -- 
    SELECT c1, p1, c3.company, c3.employee, path || c3.employee 
    FROM shortest_path c1 
    JOIN CompanyInfo c2 ON c1.p2 = c2.employee  
    JOIN CompanyInfo c3 ON c3.company = c2.company 
     AND NOT c3.employee = ANY (c1.path) 
) 

SELECT *, array_length(path,1) -1 as distance 
FROM shortest_path 
WHERE p2 = 'Peter' 
ORDER BY distance 
LIMIT 1; 
+0

完美,謝謝:) –