回复 ID 的预期顺序:55, 57, 58, 59, 60, 56 -- 这样整个 1st parent 回复及其所有子项出现在 2nd parent 回复之前 以下 SQL 查询返回错误的结果顺序
WITH RECURSIVE t(replyid, replypid, depth, path, reply, replied, reply_userid) AS (
(SELECT replyid, replypid, 0, array[replyid], reply, replied, replies.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = replies.replyid) AS reply_revs
FROM replies
LEFT OUTER JOIN users u ON (replies.userid = u.userid)
WHERE replypid is NULL AND postid = 31 ORDER BY replied)
UNION ALL
(SELECT r.replyid, r.replypid, t.depth+1, t.path || r.replypid, r.reply, r.replied, r.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = r.replyid)
FROM replies r
JOIN t ON (r.replypid = t.replyid)
LEFT OUTER JOIN users u ON (r.userid = u.userid)
ORDER BY replied)
) SELECT * FROM t
replyid replypid depth path reply replied
55 NULL 0 {55} 1st parent reply 2011-02-13 11:40:48.072148-05
56 NULL 0 {56} 2nd parent reply 2011-02-13 11:41:00.610033-05
57 55 1 {55,55} 1st child to 1st parent reply 2011-02-13 11:41:26.541024-05
58 55 1 {55,55} 2nd child to 1st parent reply 2011-02-13 11:41:39.485405-05
59 55 1 {55,55} 3rd child to 1st parent reply 2011-02-13 11:41:51.35482-05
60 59 2 {55,55,59} 1st child to 3rd child of 1st parent reply 2011-02-13 11:42:14.866852-05
但是,仅将“ ORDER BY path”添加到末尾即可解决此问题,但仅适用于升序
WITH RECURSIVE t(replyid, replypid, depth, path, reply, replied, reply_userid) AS (
(SELECT replyid, replypid, 0, array[replyid], reply, replied, replies.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = replies.replyid) AS reply_revs
FROM replies
LEFT OUTER JOIN users u ON (replies.userid = u.userid)
WHERE replypid is NULL AND postid = 31 ORDER BY replied)
UNION ALL
(SELECT r.replyid, r.replypid, t.depth+1, t.path || r.replypid, r.reply, r.replied, r.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = r.replyid)
FROM replies r
JOIN t ON (r.replypid = t.replyid)
LEFT OUTER JOIN users u ON (r.userid = u.userid)
ORDER BY replied)
) SELECT * FROM t ORDER BY path
replyid replypid depth path reply replied
55 NULL 0 {55} 1st parent reply 2011-02-13 11:40:48.072148-05
57 55 1 {55,55} 1st child to 1st parent reply 2011-02-13 11:41:26.541024-05
58 55 1 {55,55} 2nd child to 1st parent reply 2011-02-13 11:41:39.485405-05
59 55 1 {55,55} 3rd child to 1st parent reply 2011-02-13 11:41:51.35482-05
60 59 2 {55,55,59} 1st child to 3rd child of 1st parent reply 2011-02-13 11:42:14.866852-05
56 NULL 0 {56} 2nd parent reply 2011-02-13 11:41:00.610033-05
因此,让我们现在尝试 DESCENDING,而不是附加“ ORDER BY path DESC” 结果是:
replyid replypid depth path reply replied
56 NULL 0 {56} 2nd parent reply 2011-02-13 11:41:00.610033-05
60 59 2 {55,55,59} 1st child to 3rd child of 1st parent reply 2011-02-13 11:42:14.866852-05
57 55 1 {55,55} 1st child to 1st parent reply 2011-02-13 11:41:26.541024-05
58 55 1 {55,55} 2nd child to 1st parent reply 2011-02-13 11:41:39.485405-05
59 55 1 {55,55} 3rd child to 1st parent reply 2011-02-13 11:41:51.35482-05
55 NULL 0 {55} 1st parent reply 2011-02-13 11:40:48.072148-05
现在看起来好像第一个父母回复的孩子是第二个父母回复的孩子。
我的问题是:如何对结果进行排序,以便深度 > 0 的子项或结果始终出现在其相应的父项之后而不是其他父项之后?
我想看到的结果:
replyid replypid depth path reply replied
56 NULL 0 {56} 2nd parent reply 2011-02-13 11:41:00.610033-05
55 NULL 0 {55} 1st parent reply 2011-02-13 11:40:48.072148-05
57 55 1 {55,55} 1st child to 1st parent reply 2011-02-13 11:41:26.541024-05
58 55 1 {55,55} 2nd child to 1st parent reply 2011-02-13 11:41:39.485405-05
59 55 1 {55,55} 3rd child to 1st parent reply 2011-02-13 11:41:51.35482-05
60 59 2 {55,55,59} 1st child to 3rd child of 1st parent reply 2011-02-13 11:42:14.866852-05
感谢 Freenode 上#postgresql 中的 RhodiumToad,我能够提出以下 PHP 和 SQL 查询,效果非常好!
if (isset($_SESSION["userid"])) {
$s_col1 = ", (SELECT COUNT(*) FROM votes WHERE replyid = replies.replyid AND userid = %d) AS reply_voted";
$s_col2 = ", (SELECT COUNT(*) FROM votes WHERE replyid = r.replyid AND userid = %d)";
} else { $s_col1 = ""; $s_col2 = ""; }
if ($sort == "newest") { $s_arr1 = "-extract(epoch from replied)::integer"; $s_arr2 = " || -extract(epoch from r.replied)::integer"; }
else if ($sort == "oldest") { $s_arr1 = "extract(epoch from replied)::integer"; $s_arr2 = " || extract(epoch from r.replied)::integer"; }
else if ($sort == "topvotes") { $s_arr1 = "-votes"; $s_arr2 = " || -r.votes"; }
else { $s_arr1 = ""; $s_arr2 = ""; }
$sql = "WITH RECURSIVE t(replyid, replypid, depth, path, reply, replied, reply_userid) AS (
(SELECT replyid, replypid, 0, array[$s_arr1,replyid], reply, replied, replies.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = replies.replyid) AS reply_revs,
(SELECT COUNT(*) FROM votes WHERE replyid = replies.replyid) AS reply_votes
$s_col1
FROM replies
LEFT OUTER JOIN users u ON (replies.userid = u.userid)
WHERE replypid is NULL AND postid = %d)
UNION ALL
(SELECT r.replyid, r.replypid, t.depth+1, t.path$s_arr2 || r.replyid, r.reply, r.replied, r.userid, u.displayname, u.email_address,
(SELECT COUNT(*) FROM reply_revs WHERE replyid = r.replyid) AS reply_revs,
(SELECT COUNT(*) FROM votes WHERE replyid = r.replyid) AS reply_votes
$s_col2
FROM replies r
JOIN t ON (r.replypid = t.replyid)
LEFT OUTER JOIN users u ON (r.userid = u.userid))
) SELECT * FROM t ORDER BY path";