The question in a nutshell: For each row in a forums
table, how can I efficiently get the number of rows of the forum_threads
table and the forum_posts
table that have the respective forum_id
value?
I have a page showing a list of forums. For each forum, I would like to show the number of threads and the number of posts contained in that forum, and the time of the most recent post. I store forum data in three tables:
forums
which contains the forum ID, forum name, etc. Indeces are onforum_id
(primary) andordering
forum_threads
which contains the thread ID, forum ID, thread title, etc. Indeces are onthread_id
(primary),forum_id
forum_posts
which contains the post ID, thread ID, forum ID, message content, timestamp, etc. Indeces are onpost_id
(primary),thread_id
anduser_id
.
My (inefficient) code for generating the information I require goes as follows:
- select all rows in the `forums` table
- foreach row:
- perform a count(thread_id) query in the `forum_threads` table matching this `forum_id`
- perform a count(post_id) query in the `forum_posts` table matching this `forum_id`
This is starting to take far too long to compute, and so I am trying to optimize it. I figured let's start with just the num_threads
and num_posts
bit within a single query:
SELECT
`forums`.`forum_id`,
`name`,
`description`,
count(forum_threads.thread_id) as num_threads,
count(forum_posts.post_id) as num_posts
FROM
(`forums`)
JOIN
`forum_threads` ON `forums`.`forum_id`=`forum_threads`.`forum_id`
JOIN
`forum_posts` ON `forums`.`forum_id`=`forum_threads`.`forum_id`
WHERE `hidden` = 0
ORDER BY `ordering`
However, this query fails because there are simply too many posts for the second join to handle. It spins at 100% cpu for a bit, and then fails with error 126 (which I gather typically results from overloading resources). In any case, it succeeds if I comment out that line, and fails when I include it.
What is the efficient way to get the number of rows of two separate tables that share an ID with the row in a "parent" table, without performing multiple separate queries for each result in a previous query?