0

投稿にネストされたコメントが添付されたアプリをセットアップしました。コメントにクロージャ テーブル方式 (スライド 40)を使用することにしました。これは、ハード ディスク容量がいかに安価であるかと比べて、ツリー構造のクエリと管理がいかに簡単に見えるかという理由によるものです。しかし、問題が発生しています。祖先 ID ではなく、投稿 ID に基づいてツリー パスを取得する方法がわかりません (スライド 49)。

私のデータベース構造は次のようになります。

table: comment_paths
--------------------
parent_id (fk on comments.id)
child_id  (fk on comments.id)
depth

table: comments
---------------
id
parent_id (fk on comments.id)
post_id   (fk on posts.id)
text

table: posts
---------------
id
name

スライドショーのように、事前にparent_idがわかっている場合は、ツリーを簡単に取得できます:

SELECT c.*, p.*
FROM comments AS c
JOIN comment_paths AS p
ON c.id = p.child_id
WHERE p.parent_id = 1

parent_idただし、事前にわかりません。しか知らないpost_id。データベースのセットアップ方法では、投稿に複数のツリーが関連付けられています。

                 [post]
-----------------------------------------
[comment]       [comment]       [comment]   depth: 0
    |                               |
 [reply]                         [reply]    depth: 1
  |   |
 [r] [r]                                    depth: 2

私の最初の解決策は、次のようなクエリでした。

SELECT c.*, p.*
FROM comments AS c
JOIN comment_paths AS p
ON c.id = p.child_id
WHERE p.parent_id IN
    (SELECT id FROM comments WHERE parent_id IS NULL AND post_id = 6)

それは正しいデータを返しますが、そのような入れ子になった SELECT は正しくないように感じます。これを行うより良い方法はありますか?

ありがとう!

4

1 に答える 1

2

私は本当に良い方法を考えることはできません。私が行う唯一の変更は、IN の代わりに EXISTS を使用することです。

SELECT c.*, p.*
FROM comments AS c
JOIN comment_paths AS p
ON c.id = p.child_id
WHERE EXISTS
(SELECT * FROM comments c2 WHERE p.parent_id = c2.id AND c2.parent_id IS NULL AND c2.post_id = 6)

しかし、実際にはもっと良い方法があるかどうかを知りたいと思っています。

アップデート:

使用している RDMS がわかりません。しかし、再帰クエリが利用できる場合は、comments_path テーブルから完全に離れることができると思います。

;with cte as(
select c.*, 0 as depth
from comments c
where c.post_id = 6 and c.parent_id is null
union all
select c.*, cte.depth + 1
from comments c
join cte on c.parent_id = cte.id)

select * from cte
于 2013-04-17T17:09:29.703 に答える