1

MySQL と PHP のスレッド コメント システムを開発しています。Closure Table パターンを選択しましたが、問題があります。ツリー全体を取得するには、クエリ (クエリ) が必要です。どうやってするか?これについて多くのことを検索しましたが、最適なものが見つかりません。スレッド化されたコメントに適したものがあれば、お知らせください。お返事ありがとうございます。

4

3 に答える 3

2

これは私がこれまでに持っているものです:

SELECT `Comments`.* FROM `Comments`
LEFT JOIN `TreePaths` ON `Comments`.`iD` = `TreePaths`.`descendant`
WHERE `TreePaths`.`ancestor` = <Root ID>

これにより、特定のツリーのすべてのノードがクロージャテーブルからプルされますが、現時点では正しく順序付けられていません。最後の部分がわかれば、この投稿を更新します。プログラム的には、結果セットの情報を使用して正しい順序を取得できますが、結果では正しい順序であることが望ましいです。

于 2011-11-27T17:37:21.963 に答える
2

このユースケースがアプリケーションで一般的なものである場合は、ルート ID (ツリーのルートの ID。これは、これらのコメントが属する投稿の ID にすることができます) を保存するだけです。コメントのツリー全体を取得する必要がある場合は、次のようにするだけです。

SELECT * FROM comments WHERE root_id = <root_id>

またはあなたの設計のための同等のクエリ。テーブル定義を提供していただければ、特定のクエリについてお手伝いできます。

アップデート:

$dbh = new PDO($dsn, $user, $password);
$sql = "SELECT A.*, GROUP_CONCAT(descendant) as descendants FROM Comments AS A INNER JOIN Paths AS B ON A.id = B.ancestor WHERE A.item = ? GROUP BY A.id";
$stmt = $dbh->prepare($sql);
$stmt->execute(array($item));
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);

$adjacency_list = array(); $comments = array();
foreach($data as $row) {
    $comments[$row['id']] = $row;
    $descendants = explode(',', $row['descendants']);
    $adjacency_list[$row['id']] = $descendants;
}

echo '<UL>';
foreach($adjacency_list[$item] as $top_level_comment) {
    printTree($top_level_comment, $adjacency_list[$top_level_comment]);
}
echo '</UL>';

function printTree($node, $descendants) {
    echo '<LI>'.$node;
    if(sizeof($descendants) > 0) {
        echo '<UL>';
        foreach($descendants as $descendant) {
            $d = array();
            if(!empty($adjacency_list[$descendant])) $d = $adjacency_list[$descendant];
            printTree($descendant, $adjacency_list[$descendant]);
        }
        echo '</UL>';
    }
    echo '</LI>';
}

一方、ネストされたセット モデルは、挿入と更新が頻繁に行われるため、コメント システムには適していません。データがめったに更新されない場合、これは効率的なソリューションです。

于 2011-09-20T14:59:21.027 に答える
1

クロージャーテーブルも見ているので、あなたの質問に出くわしました。Bill Karwin の著書 "Sql anti-patterns" のクロージャ テーブルに関するアドバイスに従えば、問題は解決できると思います。

先祖/子孫の関係を共有するツリー内のノードのペアごとに、このテーブルに 1 つの行を格納します。ツリー内でノードが 複数のレベルで分離されている場合でも同様です

(私の強調)

したがって、1 回のクエリでparentId親のすべての子が一度に生成されます。(SQL サーバーでは、これは再帰クエリによって実行できます)。

と:

Closure Table を改善して、直接の親ノードまたは子ノードのクエリをより簡単にすることができます。TreePaths.path_length 属性を Closure Table デザインに追加します。

つまり、アイテム間の距離をクロージャー テーブルに格納します。

あなたは彼の例を本当に気に入ると思います。コメントスレッドについても同様です。

于 2011-12-08T15:34:33.317 に答える