Reputation: 19
This is a common greatest-n-per-group question, but with an extra problem. What i want is to find the latest 20 posts of a user, and for each post, load its latest 5 (or n) comments. Moreover, for pagination needs, i need to know how many other comments each post has. Is it possible to find it out with the same query? (Or at least with the less efficient queries needed)
What i've done now is finding the latest posts and their comments(all):
Finding latest posts of user:
SELECT up.primkey
, up.sender
, up.comment
, up.date
, up.admin_approved
, u.username
, u.avatar
FROM users_posts up
JOIN users u
ON up.sender=u.userkey
WHERE up.sender=?
AND up.admin_approved=0
ORDER
BY primkey DESC LIMIT $from,$to;
Then,i store each primkey in an array, in order to retrieve the comments of these posts.
Finding the comments of the posts:
SELECT c.primkey,c.post_id, c.sender, c.comment, c.date, u.username, u.avatar
FROM users_posts_comments c
LEFT JOIN users u ON c.sender=u.userkey
WHERE c.post_id IN('.implode(",", $posts_array).') AND c.`admin_approved`=0
ORDER BY c.primkey DESC;
After that, i store each comment to a new array ($comments[$post_id][]=comment info)
and then i output the result.
What i want is to modify the second query and limit the comments to the 5 recent, and also to find somehow how many are the total comments of each post in order to show the pagination.
Here's a fiddle... sqlfiddle.com/#!2/e92a6/1
Expected result:
post8
post7
comment-7
comment-6
comment-5
{pages}
post6
...
I know it would be difficult, so what would you recommend me to do(the most efficient way)?
Thanks.
Upvotes: 0
Views: 759
Reputation: 33945
A faster solution uses variables - but I'm old school...
This query gives you the latest 5 posts for each sender...
SELECT x.* ,COUNT(*)
FROM users_posts x
JOIN users_posts y
ON y.sender = x.sender
AND y.date >= x.date
GROUP
BY x.primkey
HAVING COUNT(*) <= 5
So now you can extend that idea to return the 3 most recent comments (if any) for each of those last 5 posts (for each sender)
SELECT a.*, upc.*
FROM
( SELECT x.*
FROM users_posts x
JOIN users_posts y
ON y.sender = x.sender
AND y.date >= x.date
GROUP
BY x.primkey
HAVING COUNT(*) <= 5
) a
LEFT
JOIN users_posts_comments upc
ON upc.post_id = a.primkey
LEFT
JOIN users_posts_comments z
ON z.post_id = upc.post_id
AND z.date >= upc.date
GROUP
BY a.sender
, a.primkey
, upc.primkey
HAVING COUNT(upc.post_id) <= 3;
Upvotes: 1