Как сохранить порядок появления детей после родителей - PullRequest
0 голосов
/ 14 февраля 2011

Ожидаемый порядок по replyid: 55, 57, 58, 59, 60, 56 - чтобы весь 1-й родительский ответ и все его дочерние элементы появлялись ДО 2-го родительского ответа. Следующий 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

Благодаря 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";

Ответы [ 2 ]

1 голос
/ 15 февраля 2011

В вашем последнем запросе действительно есть два вида в одном. Родители могут сортировать по возрастанию или по убыванию, а дети могут сортировать только по возрастанию.

Посмотрев на это, я верю, что вы можете найти решение с чем-то вроде этого.

   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;

Я считаю, что логика логична, но вы должны выяснить, как заменить числа в порядке убывания, поскольку все будет «вверх ногами». (Возможно, поменять позиции массива)

0 голосов
/ 14 февраля 2011

Что делает ребенка первым ребенком?Если это ответная дата, вы должны также упорядочить ее по этому значению.

...