treeface
treeface

Reputation: 13351

Reading most recent values in a join without performing a nested SELECT

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!

Upvotes: 0

Views: 237

Answers (2)

OMG Ponies
OMG Ponies

Reputation: 332731

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

Upvotes: 3

user359040
user359040

Reputation:

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

Upvotes: 0

Related Questions