LIMIT - results of nested JOIN queries

I honestly have no idea how to give a better name for this :(

I basically have these 3 tables

Table "public.users"
Column |         Type          |                     Modifiers
--------+-----------------------+----------------------------------------------------
id     | integer               | not null default nextval('users_id_seq'::regclass)
name   | character varying(40) |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "comments" CONSTRAINT "comments_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE

Table "public.comments"
Column  |  Type   |                       Modifiers
---------+---------+-------------------------------------------------------
id      | integer | not null default nextval('comments_id_seq'::regclass)
user_id | integer |
content | text    |
Indexes:
"comments_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"comments_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE

Table "public.votes"
Column   |  Type   |                     Modifiers
------------+---------+----------------------------------------------------
id         | integer | not null default nextval('votes_id_seq'::regclass)
up         | boolean | default false
comment_id | integer |
Indexes:
"votes_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"votes_comment_id_fkey" FOREIGN KEY (comment_id) REFERENCES comments(id) ON UPDATE CASCADE ON DELETE CASCADE

I want to select all users (including those who have no comments) and include 3 comments for each user, and then select 2 votes for each comment (including those comments that have no vote)

What I still have is a request to select 3 comments for each user.

SELECT users.id as userId, comments.id as commentId, users.name, comments.content, comments.rn
FROM users
LEFT JOIN (
  SELECT *, row_number() OVER (PARTITION BY comments.user_id) as rn FROM comments
) as comments
ON users.id = comments.user_id
WHERE comments.rn <= 3 OR comments.rn IS NULL;
+4
source share
3 answers

You have the right idea. Just continue with it:

SELECT u.id as userId, c.id as commentId, u.name, c.content, c.rn
FROM users u LEFT JOIN
     (SELECT c.*,
             ROW_NUMBER() OVER (PARTITION BY c.user_id) as rn
      FROM comments c
     ) c
    ON u.id = c.user_id LEFT JOIN
    (SELECT v.*,
            ROW_NUMBER() OVER (PARTITION BY v.comment_id) as rn
     FROM votes v
    ) v
    ON c.id = v.comment_id
WHERE (c.rn <= 3 OR c.rn IS NULL) and
      (v.rn <= 2 or v.rn IS NULL);
+2
source

" ", CxV (3x2 = 6) .

, 1 , dense_rank() row_number(), "" rn < 4

select * from (
    select *,
        dense_rank() over (partition by u.id order by c.id) rn,
        dense_rank() over (partition by c.id order by v.id) rn2
    from users u
    left join comments c on c.user_id = u.id
    left join votes v on v.comment_id = c.id
) t where rn < 4 and rn2 < 3
+2

It will probably be more convenient for indexing:

select
  *
from
  users u
    left join lateral (select * from comments c where u.id = c.user_id order by c.id limit 3) c on (u.id = c.user_id)
      left join lateral (select * from votes v where c.id = v.comment_id order by v.id limit 2) v on (c.id = v.comment_id)
+2
source

All Articles