Question

In the interest of eliminating as many nested queries as possible, I'm trying to optimize the following query:

   SELECT fp.id, 
          fp.user_id, 
          COUNT(c.id) AS num_replies, 
          c2.created AS latest_activity_time, c2.user_id AS latest_activity_user_id
     FROM forum_posts fp
LEFT JOIN comments c ON c.object_id = fp.id
LEFT JOIN (SELECT created, user_id
             FROM comments 
         ORDER BY created DESC 
            LIMIT 1) AS c2 ON fp.id = c2.object_id
    WHERE fp.deleted != 1
 GROUP BY fp.id

Sorry if you find any errors...I tried whittling this query down to only the relevant parts and I might have made a mistake somewhere in the process

So basically, what we have here is a table of forum posts and a table of comment replies to those posts. Each forum post can have multiple replies. The first join is used for counting the total number of replies, and the second join is used to get the most recent reply's information. What I get back from this query is something like this:

sample nested query results

So, I'm basically trying to figure out how I can do this without having to resort to this nested query. Any help you guys can provide would be extremely useful.

Thanks!

Edit: I've adjusted the query slightly to reflect the fact that I need to pull back not just the latest_activity_time, but also the latest_activity_user_id. Sorry for the confusion!

Was it helpful?

Solution

Use:

   SELECT fp.id,
          fp.user_id,
          COUNT(a.id) AS num_replies,
          c.date AS latest_activity_time,
          c.user_id AS latest_activity_user_id
     FROM FORUM_POSTS fp
LEFT JOIN COMMENTS a ON a.object_id = fp.id         
LEFT JOIN (SELECT x.object_id,
                  x.date, 
                  x.user_id
             FROM COMMENTS x
             JOIN (SELECT t.object_id,
                          MAX(t.date) AS max_date
                     FROM COMMENTS t
                 GROUP BY t.object_id) y ON y.object_id = x.object_id
                                        AND y.max_date = x.date) b ON b.object_id = fp.id
    WHERE fp.deleted != 1
 GROUP BY fp.id

OTHER TIPS

As you are using MySQL, you should be able to get away with the following:

   SELECT fp.id, 
          fp.user_id, 
          COUNT(c.id) AS num_replies, 
          c.created AS latest_activity_time, 
          c.user_id AS latest_activity_user_id
     FROM forum_posts fp
LEFT JOIN comments c ON c.object_id = fp.id
    WHERE fp.deleted != 1
 GROUP BY fp.id
 ORDER BY fp.id, c.created
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top