Re: Recursive CTE trees + Sorting by votes - Mailing list pgsql-general

From Paul Jungwirth
Subject Re: Recursive CTE trees + Sorting by votes
Date
Msg-id CA+6hpanROV3vJA+N0fgcxCwq9oonnq7W2PRG8fEYMUWNew+GQg@mail.gmail.com
Whole thread Raw
In response to Re: Recursive CTE trees + Sorting by votes  (Martijn van Oosterhout <kleptog@svana.org>)
Responses Re: Recursive CTE trees + Sorting by votes  (Gregory Taylor <gtaylor@gc-taylor.com>)
List pgsql-general
> Or another idea, add a column that is the path of the parent:

I don't think this will work. The problem is you need the full path to
keep the children with their parents, but you also need the score. If
you make the path an array of (-votes, id) tuples (perhaps flattened
for simplicity), then you get the correct ordering. That way at every
stage you are sorting by votes, but still keeping children with their
parents:

comments=> WITH RECURSIVE cte (id, message, author, path, parent_id,
depth, votes)  AS (
    SELECT  id,
        message,
        author,
        array[-votes,id] AS path,
        parent_id,
        1 AS depth, votes
    FROM    comments
    WHERE   parent_id IS NULL
    UNION ALL
    SELECT  comments.id,
        comments.message,
        comments.author,
        cte.path || -comments.votes || comments.id,
        comments.parent_id,
        cte.depth + 1 AS depth, comments.votes
    FROM    comments
    JOIN cte ON comments.parent_id = cte.id
    )
    SELECT id, message, author, path, depth, votes FROM cte
ORDER BY path;
 id |           message           | author |       path        | depth | votes
----+-----------------------------+--------+-------------------+-------+-------
  5 | Very interesting post!      | thedz  | {-3,5}            |     1 |     3
  8 | Fo sho, Yall                | Mac    | {-3,5,-12,8}      |     2 |    12
  7 | Agreed                      | G      | {-3,5,-5,7}       |     2 |     5
  6 | You sir, are wrong          | Chris  | {-3,5,-3,6}       |     2 |     3
  1 | This thread is really cool! | David  | {-1,1}            |     1 |     1
  3 | I agree David!              | Daniel | {-1,1,-4,3}       |     2 |     4
  2 | Ya David, we love it!       | Jason  | {-1,1,-3,2}       |     2 |     3
  4 | gift Jason                  | Anton  | {-1,1,-3,2,-15,4} |     3 |    15
(8 rows)

Time: 0.966 ms

Paul


On Wed, Aug 6, 2014 at 2:38 PM, Martijn van Oosterhout
<kleptog@svana.org> wrote:
> On Wed, Aug 06, 2014 at 05:28:09PM -0400, Gregory Taylor wrote:
>> We are working on a threaded comment system, and found this post by Disqus
>> to be super helpful:
>>
>> http://cramer.io/2010/05/30/scaling-threaded-comments-on-django-at-disqus/
>>
>> The CTE works wonderfully, and we're really happy with the results. The
>> last obstacle is figuring out how to sort by a "votes" field, meanwhile
>> preserving the tree structure.
>
> What do you mean exactly? Do you mean that want everything at the same
> level to be sorted by vote?
>
>> If we "ORDER BY path, votes" (assuming we have the same structure as in the
>> article), we never need tie-breaking on "path", so the "votes" part of this
>> doesn't even come into the equation.
>>
>> I suspect we need to do some path manipulation, but I'm not too sure of
>> where to begin with this. I attempted incorporating "votes" into the path,
>> but I failed pretty badly with this. It's probably way off, but here's my
>> last (failed) attempt:
>>
>> https://gist.github.com/gtaylor/e3926a90fe108d52a4c8
>
> I think what you need to do is do the ordering withing the CTE itself.
> Something like:
>
> WITH RECUSIVE cte () AS (
>    SELECT ... ORDER BY vote DESC
> UNION ALL
>    SELECT ... JOIN cte ... ORDER BY vote DESC
> ) SELECT * from cte;
>
> Or another idea, add a column that is the path of the parent:
>
> WITH RECUSIVE cte () AS (
>    SELECT array[] as path_parent, array[id] as path, ... ORDER BY vote DESC
> UNION ALL
>    SELECT cte.path as path_parent, cte.path || comments.id as path, ... JOIN cte ... ORDER BY vote DESC
> ) SELECT * from cte order by path, votes desc;
>
> Hope this helps,
> --
> Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
>> He who writes carelessly confesses thereby at the very outset that he does
>> not attach much importance to his own thoughts.
>    -- Arthur Schopenhauer
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
>
> iQIVAwUBU+KgXUvt++dL5i1EAQgKzQ//fWqd56vcwKsYQDtbUE3Q2/ohUinYxpb6
> HgS9HoEs8QU3b4yzE6VOVXcUcN3/z6PPx4Mz3rqFOVgsFcZR2umGAaVw5oEr57Bd
> mqFDVgUxq8Xio2tijO0XFU89fh+/Cvus08CRh+OH6POLe6M76ox6cmFPtQzeaEon
> iFKXZZRIzFv7zpoE3xsQ7wgqSF44L0TIJIjdw3Dhcs8fN+T/jO0hJtUMKidGwbbv
> 9f08r9kjSMBYAhKCPXZHy/By/E91DhA8GjJFL1MloHPol/lzSkn7v7amWJZaILyE
> g3ghGUG1YhPJPA3Dw2VBKWzumNyu8kXSzTvzN6PacFToCf2ZIfTJH59ehPqztt0o
> FC6auCvO1vWS3NbOKSwdBVvXb/bJsIM3uqN16LSVhHqUp75eOFp5AWKJMCjQF1hE
> MkHk5xyz2CWsYZTlzqCKtGxRjFEbxKGjtqsxcM4qKM3uSjMG/ZhaAY6FZFLIage0
> yxsHrE5N+zfDAGV1EplxxtzMHUEqyFnBYQNRHUSChLPCkgrluOeFFRQU22aVpUUL
> vbPIBI8E16bbtU6zwnE3DoMdBm1Pq5E4c+URbfbzJhGB1e/DkDqf7pOZjojLJ9ue
> DRP777bBbsYwtCdS69kiIDkfwA2f7lliILI9wpnKSg64SIWlCR6NVWFTsfU8OP4l
> cJw8kApkDr4=
> =8bEW
> -----END PGP SIGNATURE-----
>



--
_________________________________
Pulchritudo splendor veritatis.


pgsql-general by date:

Previous
From: Steve Clark
Date:
Subject: Re: order by question
Next
From: Adrian Klaver
Date:
Subject: Re: order by question