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 MyISAM table or id not a PRIMARY KEY , you need to create a composite ondex on (topic_id, id) .
If your InnoDB table and id are PRIMARY KEY , the index only on (topic_id) will do ( id will be implicitly added to the index).
Update
This query is likely to be even more efficient if you have indexes on (topic_id, id) and (date, id) :
See this blog post for performance details:
This request completes in 30 ms in 100,000 sample strings:
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 indices are necessary for the effective execution of this query.
If your InnoDB table and id is PRIMARY KEY , you can omit id from indexes above.