2011-02-14 30 views
0

預期順序:55,57,58,59,60,56 - 因此整個第一條父母答覆及其所有子女在第二條父母答覆前出現 下面的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路徑」到最後修復了這個,但僅限於按升序排列

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路徑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 

由於RhodiumToad在#postgresql Freenode上我能想出下面的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"; 

回答

0

什麼讓孩子成爲第一個孩子?如果是回覆的日期,則必須按此值排序。

+0

在第一組結果中,第一個孩子(或深度爲1的第一行)是第一個按照您的建議回答的日期,但是,您建議即使它已經是我必須按這個值來訂購?第二個內部SELECT語句具有「ORDER BY已回答」子句。否則,如果您的意思是添加到最後一行「ORDER BY路徑,回覆DESC」,那麼第一個答覆仍然首先出現。 – Miz 2011-02-14 21:53:07

1

在最後一次查詢中,您確實有兩種排序。父母可以升序或降序排序,但孩子只能升序排序。

看過這個後,我相信你可以得到一個像這樣的解決方案。

order by case 
     when depth = 0 
      then path 
    /* 
     secret function that always returns the 
     right numbers regardless of whether or not the sort is ascending. 
    */ 
     else XXX_function('DESC', path) 
    end desc; 

我認爲邏輯是健全的,但你必須弄清楚如何更換降序排序,因爲事情會「倒掛」的數字。 (可能會顛倒陣列位置)