[英]Order hierarchical query for comments with parent-child relation?
我有一个使用adjacency list
存储层次结构数据的注释系统(我相信),例如:MySql表具有id
, parent_id
, date
,...列,其中没有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.