2017-04-02 3 views
1

私は次のような関係があります。私は何をしようとしているRecusive SQLクエリ

会社概要(会社、役割、従業員)

は二人の従業員間の最短「パス」を見つけることです。

私はジョーとピーターの間の距離を見つける必要があります。 ジョーはA社のCEOであり、アレックスという人は役員です。 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

完璧、ありがとう:) –