I've recently began a comments/replies section for an app.
My initial approach has been to query the database for the comments linked to a particular item as below:-
$commentquery = "SELECT projects_comments.*, users.user_url, users.display_name
FROM ".$wpdb->prefix."projects_comments projects_comments
LEFT JOIN ".$wpdb->prefix."users users on users.ID=projects_comments.userid
WHERE projectid = '$projectid'
ORDER BY projects_comments.commentid DESC";
I then began a foreach
loop with the following query inside in order to retrieve the replies:
if($comments) {
foreach ( $comments as $c ) {
$replyquery = "SELECT project_replies.*, users.user_url, users.display_name
FROM ".$wpdb->prefix."project_replies project_replies
LEFT JOIN ".$wpdb->prefix."users users on users.ID=project_replies.uid
WHERE project_replies.cid = '$c->commentid'
ORDER BY project_replies.id DESC";
}
}
In practice this is all working fine, however it strikes me that this is terribly inefficient and that there must be a way to retrieve all the data in one query. My concern is that with 100 comments on a page I will be performing 100 queries for the comments alone.
What is the best method to tackle this and how would I go about combining these queries to produce one large object/array with which to pull the data from.
Or alternatively, how can I at least prevent the 'query-within-the-loop'.
SELECT c.*, cu.user_url AS cu_url, cu.display_name AS cu_name,
r.*, ru.user_url AS ru_url, ru.display_name AS ru_name
FROM projects_comments AS c
LEFT JOIN users AS cu ON cu.ID = c.userid
JOIN project_replies AS r ON r.cid = c.commentid
LEFT JOIN users AS ru ON ru.ID = r.uid
WHERE c.projectid = $projectid
ORDER BY c.commentid DESC, r.id DESC
The only detail to worry about is the JOIN instead of possibly using LEFT JOIN when connecting Project_Replies and Project_Comments. This will only pick up comments that have at least one reply; using a LEFT JOIN, you'll get comments that have no replies too.
What I tend to do to avoid this setup is this:
SELECT ...
WHERE `keyfield` IN (".implode(",",$keyvalues).")
You can JOIN
them like you do the users
table
$commentquery = "SELECT projects_comments.*, project_replies.*, users.user_url, users.display_name, users2.user_url as comment_user_url, users2.display_name as comment_display_name
from ".$wpdb->prefix."projects_comments projects_comments
LEFT JOIN ".$wpdb->prefix."project_replies project_replies ON project_replies.cid = projects_comments.comment_id
LEFT JOIN ".$wpdb->prefix."users users on users.ID=project_replies.uid
left join ".$wpdb->prefix."users users2 on users2.ID=projects_comments.userid
WHERE projectid = '$projectid'
ORDER BY projects_comments.commentid desc, project_replies.id DESC";