我有一个分层数据表(带有回复的评论),我想知道我如何对它进行排序,以便最新的评论将作为第一个和最新的回复为每个评论添加最后一个。
表
的示例下面是一个示例:
id | path | reply_to | date
1 1 NULL 8:00
2 1-2 1 9:00
3 1-3 1 10:00
4 4 NULL 11:00
5 1-5 1 12:00
6 4-6 4 13:00
7 4-7 4 14:00
如果我想选择我的结果的路径,它应该像这样排序:
4
4-6
4-7
1
1-2
1-3
1-5
是否可以使用MySQL查询?
我一直在做什么
到目前为止,我只选择了ID DESC
订购的没有回复的行,然后(对于每一行)我请求其回复并通过ID ASC
订购它们,我在PHP中使用PDO连接到我的数据库:
$stmt1 = $this->db->query("SELECT * FROM comments WHERE reply_to IS NULL ORDER BY id DESC");
$stmt2 = $this->db->prepare("SELECT * FROM comments WHERE reply_to = ? ORDER BY id ASC");
while($row = $stmt1->fetch()) {
//display the comment
$stmt2->execute(array($row['id']));
while($row2 = $stmt2->fetch()) {
//display all its replies
}
}
但是我认为如果我只查询一次,它会比我现在这样在循环中查询要好得多,对吗?
我希望我的问题是可以理解的。不幸的是,我不知道如何解决这个问题。我认为SQL join 是解决方案,但据我所知,它们"用于组合来自两个或多个表的行,基于它们之间的公共字段"。这是一个SQL的小提琴来玩。
这有点复杂,但您可以做到(至少对于问题中显示的数据)。这个想法是引入父信息("回复")。然后按以下顺序排序:
- 父母的日期和父母的id——所以所有父母的消息都在一起
- 然后将父元素放在首位
- 然后按时间排序剩余的
这是查询:
select c.*
from comments c left join
comments cparent
on c.reply_to = cparent.id
order by coalesce(cparent.date, c.date) desc,
coalesce(cparent.id, c.id),
(cparent.id is null) desc,
c.date asc;
最简单的方法:
SELECT c.* FROM
comments c
ORDER BY LEFT(c.path,1) DESC, c.path ASC
你可以在一个查询中这样做
SELECT comment.path
FROM comments AS base
LEFT JOIN comments AS comment ON (
comment.id = base.id OR -- join the parents
comment.reply_to = base.id -- join the children
)
WHERE base.reply_to IS NULL
ORDER BY comment.id