2017-06-01 17 views
0

再帰的な要求に問題があります。私が説明する前に:私はPostgreSQL 8.4を使用します。SQL再帰的クエリから余分な列を追加する

私は、2つのテーブルを、それをまとめるために、持っている:これは非常に概略図である(、ID名をして をPARENT_IDこの:ID、名前と t_packageをPACKAGE_IDは3列があります。T_OBJECTとt_package T_OBJECTは3列があります。実際には、Enterprise Architectのプロジェクトデータベースです)

t_package.parent_idは、パッケージの親パッケージです。あなたはそれを推測しました。 ブレッドクラムを再帰的にフォローすると、オブジェクトトップパッケージを取得できます。たとえば:

TOPPACKAGE 
| 
+--PACKAGE 
    | 
    +--ANOTHERPACKAGE 
     | 
     +--ANOBJECT 
     +--ANOTHEROBJECT 

事はされています。複数のトップパッケージがあることができます... 私の目的は、各オブジェクトのトップパッケージを含む余分なcolumで、T_OBJECTに基づいて、ビューを作成することです。

私は成功し、オブジェクトのトップパッケージを取得するには、再帰的な要求ceated:次に

WITH RECURSIVE parents(package_id, name, parent_id) AS (
    SELECT t_package.package_id, t_package.name, t_package.parent_id 
    FROM t_package 
    WHERE t_package.package_id = (
     SELECT package_id 
     FROM t_object 
     WHERE name = 'The name of an object' 
    ) 
    UNION 
    SELECT t_package.package_id, t_package.name, t_package.parent_id 
    FROM t_package, parents 
    WHERE parents.parent_id = t_package.package_id 
) SELECT * FROM parents WHERE parent_id = 0 

を、私はT_OBJECTプラス追加の列...これまでのところ成功だビューを作成しようとしました!

私ははっきりここにSQLで自分の限界に触れていますことを認めざるを得ない、と私はこの:(

例のデータどのように達成するかについては考えていません:

t_object: 
id;name;package_id 
1;'First object';11 
2;'Second object';11 
3;'Third object';14 
4;'Fourth object';12 

t_package: 
id;name;parent_id 
10;'First package';13 
11;'Second package';10 
12;'Third package';14 
13;'First root package';0 
14;'Second root package';0 

(PARENT_ID = 0のマークをルートパッケージ)

だから階層は次のとおりです。

First root package 
| 
+--First Package 
    | 
    +--Second package 
     | 
     +--First object 
     +--Second object 

Second root package 
| 
+--Third object 
+--Third package 
    | 
    +--Fourth object 

私が望む結果:

t_object_with_root_package: 
id;name;package_id;root_package_id 
1;'First object';11;13 
2;'Second object';11;13 
3;'Third object';14;14 
4;'Fourth object';12;14 

ご協力いただきありがとうござい

+0

あなたの質問を編集し、サンプルデータと希望する結果を提供してください。 –

+1

Sidequestion:(非常に)古いバージョン、8.4を使用していますか?もともとそれに基づいていたそのバリエーション(赤方偏移、緑色のプラムなど)の1つではありませんか? – pozs

+0

私は絶対にバージョンを確信しています。それは純粋なPostgreSQL 8.4です。そして、はい、古いです^^ – deadbird

答えて

2

は、これは、同様に8.4で動作するはずです:

WITH RECURSIVE rcte(id, name, package_id, root_package_id) AS (
    SELECT o.id, o.name, p.id, p.id 
    FROM  t_package p 
    LEFT JOIN t_object o ON o.package_id = p.id 
    WHERE  p.parent_id = 0 
    UNION 
    SELECT o.id, o.name, c.id, p.root_package_id 
    FROM  rcte p 
    JOIN  t_package c ON c.parent_id = p.package_id 
    LEFT JOIN t_object o ON o.package_id = c.id 
) 
SELECT * 
FROM  rcte 
WHERE id IS NOT NULL 
ORDER BY id 

をしかし、今私は9.6でテストできます。 http://rextester.com/QCZPS53546

ここでの主なアイデアは、最初にルートエンティティを選択することです。その後、階層の葉まですべてのパスを通過します。また、各ステップのt_objectをすべてLEFT JOINで収集してください(したがって、rCTEの出力にはNULLが含まれます(t_packageにはt_objectが含まれていません)。

+0

これは完全に機能します!どうもありがとう! – deadbird

0

言葉、それは本当にボトムアップからの子孫のリストを構築しているとして、あなたのRCTEで両親は、誤解を招く:

WITH RECURSIVE descendent AS (
    SELECT t_package.* FROM t_package 
    WHERE package_id in (select package_id from t_object) 
    UNION ALL 
    SELECT t_package.* FROM t_package, descendent 
    WHERE t_package.package_id = descendent.parent_id 
) 
SELECT * FROM descendent 

本当にあなたが先頭に開始し、することができますので、代わりにダウン仕事をしたいです一番上の親の身分証明書を持ってください。

WITH RECURSIVE ancestry(top_id, package_id, name) AS (
    SELECT t_package.package_id as top_id 
    , t_package.package_id 
    , t_package.name 
    FROM t_package where parent_id = 0 
    UNION ALL 
    SELECT ancestry.top_id 
    , t_package.package_id 
    , t_package.name 
    FROM t_package, ancestry 
    WHERE t_package.parent_id = ancestry.package_id 
) 
SELECT * 
FROM ancestry, t_object 
WHERE ancestry.package_id=t_object.package_id 

ところで、parent_id = 0とNULLではなく、むしろ混乱する可能性があります。

このフィールドにpackage_idを実装するための参照整合性チェックを可能にするには、package_id = 0のt_package行を挿入する必要があります。これは、複数のルートパッケージが存在するのではなく、ツリーの実際のルートになります。

関連する問題