繁体   English   中英

订购带有父子关系的注释的分层查询?

[英]Order hierarchical query for comments with parent-child relation?

我有一个使用adjacency list存储层次结构数据的注释系统(我相信),例如:MySql表具有idparent_iddate ,...列,其中没有parent_id的注释是主要注释和注释与parent_id自然是一个答复。

在初始页面加载时,我进行Ajax调用,该加载将加载所有注释,而无需parent_id ,因此所有主要注释都将被加载。

SELECT * FROM comms WHERE parent_id IS NULL

现在,如果任何评论都有回复,则该评论会出现一个类似“ load replies”的按钮,并且在单击时会进行另一个调用,以加载所有具有该id parent_id评论,然后递归查询将加载回复,依此类推上。 而且效果很好,问题在于,从加载顺序来看,您无法真正分辨出什么是重播。

所以我想要订购它们,以便在其所属的注释下进行重放。

现在这只能从sql中执行ORDER BY id = parent_id类的事情,对它们进行排序,以便它们在某种程度上有意义,或者我应该从php处理吗? 还是我应该重新开始并以其他方式存储它们?

编辑:第二个查询的一部分(我从前段答案中得到的例子)

SELECT date_p, parent_id, id
   FROM (SELECT * FROM comms) rec,
   (SELECT @pv := 14) initialisation
   WHERE find_in_set(parent_id, @pv) > 0 
   AND @pv := concat(@pv, ',', id) ORDER BY ?

如果我使用我喜欢的答案中提供的“替代1”,那么订购的方法会有所不同还是更好?

这就是我要达到的目标:

<p>Main comm 1</p>
  <p>reply to main comm 1</p>
  <p>another reply to main comm 1</p>
    <p> replay to reply of main comm 1</p>
  <p> yet another reply to main comm 1</p>
<p>Main comm 2</p>
<p>Main comm 3</p>

由于这需要递归,而MySQL pre v8并不真正支持该递归,因此我倾向于解决PHP中的问题,因为PHP很擅长递归。 基本例程非常简单:

function show_children($db, $parent) {
    $sql = "SELECT * FROM comms WHERE parent_id " . ($parent ? "= $parent" : "IS NULL") . " ORDER BY date_p ASC";
    $result = $db->query($sql);
    if (!$result) return;
    while ($row = $result->fetch_assoc()) {
        echo "<p>" . $row['cmt'] . "</p>";
        show_children($db, $row['id']);
    }
}

show_children($db, 0);

从对parent_id为0的show_children的调用开始,将获取所有顶级注释(parent_id = NULL的那些注释),并且递归将按日期顺序显示所有答复,但也将按其父母的顺序显示所有答复(无论是否为评论或回复)。

您还可以添加“级别”参数以允许设置输出的样式:

function show_children($db, $parent, $level = 0) {
    $sql = "SELECT * FROM comms WHERE parent_id " . ($parent ? "= $parent" : "IS NULL") . " ORDER BY date_p ASC";
    $result = $db->query($sql);
    if (!$result) return;
    while ($row = $result->fetch_assoc()) {
        echo "<p class=\"level$level\">" . $row['cmt'] . "</p>";
        show_children($db, $row['id'], $level+1);
    }
}

show_children($db, 0);

注意我假设mysqli作为数据库接口。

使用此例程,并使用以下输入数据:

id  date_p      parent_id   cmt
1   2018-03-21  (null)      Main comm1
2   2018-03-22  (null)      Main comm2
3   2018-03-22  1           reply to main comm 1
4   2018-03-23  1           another reply to main comm 1
5   2018-03-23  1           yet another reply to main comm 1
6   2018-03-24  4           replay to reply of main comm 1
7   2018-03-24  (null)      Main comm3

您将获得以下输出:

<p class="level0">Main comm1</p>
<p class="level1">reply to main comm 1</p>
<p class="level1">another reply to main comm 1</p>
<p class="level2"> replay to reply of main comm 1</p>
<p class="level1"> yet another reply to main comm 1</p>
<p class="level0">Main comm2</p>
<p class="level0">Main comm3</p>

好问题:

您现在拥有的是一个好主意:

我会将其存储在3个不同的表中,

tb1)代表主评论tb2)代表主评论回复tb3)代表主评论回复。

tb1包含ID(auto_increment)之类的列成为您的主要评论ID

tb2)包含id(auto_increment),main_comment_id,reply_to_main_comment_id之类的列

tb3)具有id(auto_increment),main_comment_id,reply_to_main_comment_id,reply_reply_id

<p1>main_comment_id</p1>
  <p2>reply_to_main_comment_id</p2>
     <p3>reply_reply_id</p3>

logically like the following:

    if(p1){
       post to tb1
    }elseif(p2){
       post to tb2
    }elseif(p3){
       post to tb3
    }


To get the comments for p1, (Select comments from tb1)
To get comments for p2, (Select comments from tb2 where main_comment_id=$id)
To get comments for p3, (Select comments from tb3 where main_comment_id=$id 
 and reply_to_main_comment_id=$id2)

$sql ("SELECT comments from tb3 WHERE main_comment_id=$id1 AND reply_to_main_comment_id=$id2 ORDER BY date DESC");

当然,当您调用注释时,您将按时间顺序显示它们,从最新到最旧,您的p2成为p3的主要注释。它仅像父母和孩子,但是您以扩展的关系方式显示...。这将是正确的地方,但是评论。

希望这行得通。 我没有测试过,但是我开发了一个具有类似原理的数据库。

代码示例获得主要评论:

$comment1 = $_POST['comment1'];
$comment1_sql = ("Insert INTO tb1 (main_comment) VALUES ($comment1)");
$comment_result = mysqli_query($conn, $comment_sql1);

代码示例回复主要评论:

$comment2 = $_POST['comment2'];
$comment2_sql = ("Insert INTO tb2 (reply_to_main_comment) VALUES ($comment2)");
$comment_result = mysqli_query($conn, $comment_sql2);

与评论回复相同,对主要评论的回复

我使用MSSQL,我非常相信CROSS APPLY将为您提供帮助。 我假设MYSQL确实具有该join。

例如

SELECT A.PARENT_ID,A.COMMENT,* FROM T A 
CROSS APPLY T B 
where a.id = 3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM