Getting the SUM() of claps and at the same time counting bookmarks in one query

You need to aggregate before doing the joins. One method is:

SELECT p.*, u.name, u.avatar, 
       b.bookmarksCount, c.totalClaps
FROM posts p LEFT JOIN 
     users u
     ON u.id = p.owner LEFT JOIN
     (SELECT b.post_id, COUNT(*) as bookmarksCount
      FROM bookmarks b
      GROUP BY b.post_id
     ) b
     ON b.post_id = p.id LEFT JOIN
     (SELECT c.post_id, SUM(claps_count) as totalClaps
      FROM claps c
      GROUP BY c.post_id
     ) c
     ON c.post_id = p.id;

Note that no aggregation is needed in the outer query.

The above should have good performance if you are interested in all posts. If you are filtering the posts by any criteria, then correlated subqueries are probably a better solution:

SELECT p.*, u.name, u.avatar, 
       (SELECT COUNT(*)
        FROM bookmarks b
        WHERE b.post_id = p.id
       ) as bookmarksCount,
       (SELECT SUM(claps_count)
        FROM claps c
        WHERE c.post_id = p.id
       ) as totalClaps
FROM posts p LEFT JOIN 
     users u
     ON u.id = p.owner LEFT JOIN
      b
     ON b.post_id = p.id;

For this, you want indexes on bookmarks(post_id) and claps(post_id, claps_count).

Leave a Comment