I built a custom forum for my site using MySQL. The listing page is essentially a table with the following columns: Topic, Last Updated, and
You may want to break it up into a set of subqueries (as inner queries). I'd need the schema to really play, but if you
SELECT t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies
FROM (
SELECT (id, name, date)
FROM wp_pod_tbl_forum
WHERE topic_id = 0
) as t
LEFT OUTER JOIN
wp_pod_tbl_forum r
WHERE
r.topic_id = t.id
GROUP BY
t.id
ORDER BY
date DESC LIMIT 0,20;
that may help speed it up a little, it may not even be the best answer (errors may exist).
There are tons of ways to do it, but the most important thing to do when SQL tuning is to reduce each set as much as possible before performing an operation.
SELECT id, name, last_reply, replies
FROM (
SELECT topic_id, MAX(date) AS last_reply, COUNT(*) AS replies
FROM wp_pod_tbl_forum
GROUP BY
topic_id
) r
JOIN wp_pod_tbl_forum t
ON t.topic_id = 0
AND t.id = r.topic_id
UNION ALL
SELECT id, name, date, 0
FROM wp_pod_tbl_forum t
WHERE NOT EXISTS
(
SELECT NULL
FROM wp_pod_tbl_forum r
WHERE r.topic_id = t.id
)
AND t.topic_id = 0
ORDER BY
date DESC
LIMIT 0, 20
If your table is MyISAM
or id
is not a PRIMARY KEY
, you need to create a composite ondex on (topic_id, id)
.
If your table is InnoDB
and id
is a PRIMARY KEY
, an index just on (topic_id)
will do (id
will be implicitly added to the index).
Update
This query will most probably be even more efficient, provided that you have indexes on (topic_id, id)
and (date, id)
:
See this article in my blog for performance details:
This query completes in 30 ms
on a 100,000
rows sample data:
SELECT id, name, last_reply,
(
SELECT COUNT(*)
FROM wp_pod_tbl_forum fc
WHERE fc.topic_id = fl.topic_id
) AS replies
FROM (
SELECT topic_id, date AS last_reply
FROM wp_pod_tbl_forum fo
WHERE id = (
SELECT id
FROM wp_pod_tbl_forum fp
WHERE fp.topic_id = fo.topic_id
ORDER BY
fp.date DESC, fp.id DESC
LIMIT 1
)
AND fo.topic_id <> 0
ORDER BY
fo.date DESC, fo.id DESC
LIMIT 20
) fl
JOIN wp_pod_tbl_forum ft
ON ft.id = fl.topic_id
UNION ALL
SELECT id, name, date, 0
FROM wp_pod_tbl_forum t
WHERE NOT EXISTS
(
SELECT NULL
FROM wp_pod_tbl_forum r
WHERE r.topic_id = t.id
)
AND t.topic_id = 0
ORDER BY
last_reply DESC, id DESC
LIMIT 20
Both indexes are required for this query to be efficient.
If your table is InnoDB
and id
is a PRIMARY KEY
, then you can omit id from the indexes
above.