我有一个使用adjacency list
来存储分层数据的评论系统(我相信),例如:MySql表包含id
,parent_id
,date
列,...,没有parent_id
的评论是主要评论,而parent_id
的评论自然是回复。
在初始页面加载时,我进行Ajax调用,加载所有注释,而不是parent_id
,所以所有主要注释。
SELECT * FROM comms WHERE parent_id IS NULL
现在,如果任何评论都回复了一个按钮,例如"加载回复"对于该注释显示,并且单击另一个调用,加载所有注释为parent_id
的注释id
的注释,然后递归查询加载回复的回复,依此类推。这很有效,问题在于,根据它们的加载顺序,您无法确定什么是重放。
所以我想要的是订购它们,以便重播在它所属的评论之下。
现在这只能从sql做ORDER BY id = parent_id
这样的事情,对它们进行排序以使它们有些有意义或者我应该从php处理这个吗?或者我应该重新开始并以不同的方式存储它们?
编辑:第二个查询的一部分(取自this回答的例子,我发现了一段时间)
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>
答案 0 :(得分:2)
由于这需要递归,并且MySQL pre v8并不能真正支持它,我倾向于解决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的注释),递归将按日期顺序显示所有回复,但也按其父项的顺序显示(无论是评论还是回复)。
您还可以添加&#34;级别&#34;允许样式化输出的参数:
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>
答案 1 :(得分:-1)
很好的问题:
你现在拥有的是一个好主意:
我会将它存储在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);
与评论相同,回复主要评论的回复
答案 2 :(得分:-1)
我在MSSQL上工作,我非常确定CROSS APPLY会帮助你。我假设MYSQL确实有加入。
例如
SELECT A.PARENT_ID,A.COMMENT,* FROM T A
CROSS APPLY T B
where a.id = 3