2017-04-02 2 views
1

나는 다음과 같은 관계가 :Recusive SQL 쿼리

CompanyInfo (기업, 역할, 직원)

난 할 노력하고있어하는 두 직원 사이의 최단 "경로"를 찾는 것입니다.

I 조 피터 사이의 거리를 찾아야합니다. Joe는 A 사의 CEO이며 Alex라는 이사가 이사직을 맡고 있습니다. Alex는 B 회사의 CEO이고 Peter는 B 회사의 부사장입니다. 그러면 Joe와 Peter의 거리는 2입니다. Joe와 Peter가 같은 회사에서 역할을한다면 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

완벽한, 감사합니다 :) –