[英]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.