web-dev-qa-db-ja.com

再帰的CTEで追加の列を取得する

これは、「スレッド」が持つ子の数を取得する限りは機能しますが、親行の列をプルするように取得できないようです。親行にはparent_id is null、木はどのレベルの深さでもかまいません。

私は2つの別々のクエリでそれを行うことができますが、1つだけを使用して、子の数を取得する方法が必要です。

with recursive all_comments as (
   select id, parent_id, id as root_id
   from comment
   where parent_id is null
   union all
   select c.id, c.parent_id, p.root_id
   from comment c
     join all_comments p on c.parent_id = p.id
)
select root_id, count(*) as comment_count
from all_comments
group by root_id;

このフィドルの親contentからcomment列をプルするにはどうすればよいですか?

http://sqlfiddle.com/#!15/158ea/15

1
Mike

オプション1

RCTEのすべての反復に、追加の列(例ではcontentのみ)をすぐに含めます。 _GROUP BY_それ(それら)を外側のSELECTに追加する必要があります。
明らかに、あなたは親を数えたくないので、すぐに子供たちの最初のレベルに参加してください:

_WITH recursive tree AS (
   SELECT p.id AS root_id, c.id, p.content
   FROM   comment p
   LEFT   JOIN comment c ON c.parent_id = p.id
   WHERE  p.parent_id IS NULL

   UNION ALL
   SELECT p.root_id, c.id, p.content
   FROM   tree p
   JOIN   comment c ON c.parent_id = p.id
)
SELECT root_id, content, count(id) AS comment_count
FROM   tree
GROUP  BY 1, 2
ORDER  BY 1;
_

子のない親を保持するには、rCTEのベースSELECTで_LEFT JOIN_を使用します。したがって、外側のSELECTcount(id)を使用して、これによって生成されたNULL値を無視します。

オプション2

非常に深いツリーまたは大きな追加の列の場合、rCTEでIDを取得し、外側のcommentでもう一度テーブルSELECTに結合して、さらに列を取得する方が安価な場合があります。

_WITH RECURSIVE tree AS (
   SELECT p.id AS root_id, c.id
   FROM   comment p
   LEFT   JOIN comment c ON c.parent_id = p.id
   WHERE  p.parent_id IS NULL

   UNION ALL
   SELECT p.root_id, c.id
   FROM   tree p
   JOIN   comment c ON c.parent_id = p.id
   )
SELECT p.*, c.content  -- add more columns?
FROM  (
   SELECT root_id, count(id) AS comment_count
   FROM   tree
   GROUP  BY 1  -- cheaper ...
   ) p
JOIN   comment c ON c.id = p.root_id  -- ... but additional join
ORDER  BY p.root_id;
_

あなたのフィドルには2つのエラーがありました。この修正された SQL Fiddle を検討してください。

2

あなたのフィドルは開かないので、あなたが何を持っているのか、何が欲しいのかを正しく理解しているかどうかはわかりませんが、commentidに戻る必要があると思います。 、 このようなもの:

with recursive all_comments as (
   select id, parent_id, id as root_id
   from comment
   where parent_id is null
   union all
   select c.id, c.parent_id, p.root_id
   from comment c
     join all_comments p on c.parent_id = p.id
)
select a.root_id, a.comment_count, com.content from 
(select root_id, count(*) as comment_count
from all_comments
group by root_id) as a
inner join
comment as com
 on a.root_id = com.id and com.parent_id is null;
2
mustaccio