2017-10-19 9 views
0

私はテーブルとIDSをこのようなPostgresデータベースを持っているを探す:再帰CTEを持つすべての子孫

id INT PRIMARY KEY, 
    value TEXT, 
    parent_id INT REFERENCES ids DEFAULT NULL 

私は、この表のすべての行のための子孫の量を見つけたいです。だから、木の部分木の大きさのすべての葉のために1

になり、私は再帰CTEでこれを行うにしたいと、この書いた:

WITH RECURSIVE r AS (
SELECT id, parent_id 
from keyword 
where id=1 

UNION 

SELECT k.id, k.parent_id 
FROM keyword k 
join r on k.parent_id = r.id) 

select count(*) from r; 

を私だけではない、すべてのために、特定のidの子孫をカウントすることができます。私はCTEの中でIDでグループを書くことを試みましたが、動作しません(ほとんどの場合、サブツリーのサイズはすべての頂点に対して1になります)。この表に基づいて

id | parent_id | value 
----+-----------+-------- 
    1 |   | SELECT 
    2 |   1 | FROM 
    3 |   1 | WHERE 
    4 |   1 | ORDER 
    5 |   4 | BY 
    6 |   1 | GROUP 
    7 |   6 | BY 
    8 |   6 | HAVING 
11 |   | UPDATE 
12 |  11 | SET 
13 |  11 | WHERE 

は、私はそれを取得したい:

id | subtree_size 
-------+---------- 
1 | 11 
2 | 1 
6 | 3... 

、ツリー内にあるすべてのidの

+0

すべてのツリー:すべてのルーツから始まります: 'id = 1' - >>' where parent_id IS NULL'そして、結果にルートを保持し、外側のクエリでそれをグループ化できます。 – joop

+0

訂正:id = 1はsubtree_sizeが8です。({11,12,13}は別のツリーにあります) – joop

答えて

1
CREATE TABLE keyword 
     (id INTEGER PRIMARY KEY 
     , parent_id INT REFERENCES keyword(id) DEFAULT NULL 
     , value TEXT 
     ); 
INSERT INTO keyword(id,parent_id, value) VALUES 
(1, NULL, 'SELECT') 
,(2, 1, 'FROM') 
,(3, 1, 'WHERE') 
,(4, 1, 'ORDER') 
,(5, 4, 'BY') 
,(6, 1, 'GROUP') 
,(7, 6, 'BY') 
,(8, 6, 'HAVING') 
,(11, NULL, 'UPDATE') 
,(12, 11, 'SET') 
,(13, 11, 'WHERE') 
     ; 


WITH RECURSIVE r AS (
     SELECT id AS root -- <<== 'Anchor' the root 
     , id, parent_id 
     from keyword 
     -- where id=1 
     -- where parent_id IS NULL 
     WHERE id IN (1,2,6) -- <<== UPDATE 
UNION 
     SELECT r.root -- <<== This is the trick: maintain the parent's root 
     , k.id, k.parent_id 
     FROM keyword k 
     join r on k.parent_id = r.id 
     ) 
select distinct k.value, r.root, count(*) AS cnt 
from r 
JOIN keyword k ON k.id = r.root 
GROUP BY r.root, k.value 
     ; 
+0

r.rootは常にidであるため、実際にルートの頂点のツリー全体の子孫の数をカウントします根頂点の私はすべてのノードを通過する必要があり、それぞれがルートだったので、子孫を数えます。 –

+0

ルートが1つしかない場合、明らかに1つのグループと1つの集約が存在します。 (あなたの質問はこの点ではあまり明確ではありませんでした) – joop

+0

申し訳ありません。私はスタートポストを編集しました。 –

関連する問題