2

I am working on a custom forum for a web project. I have categories with id, topics with id and category, and posts with id and topic and user id. What I'm trying to do is display a list of the categories with data from the categories table along with data from the posts table for the newest post in that category, data for that posts's associated user, as well as some data for the topic associated with that latest post.

I've been banging my head on the wall trying to figure the query out, but I just don't have a good enough understanding of complex mysql queries to know what pattern or technique to use here. Here is what I have so far:

SELECT u1.*, fp1.*, ft1.*, fc1.* from forum_posts AS fp1
LEFT JOIN users AS u1 ON u1.id = fp1.post_by
LEFT JOIN forum_topics AS ft1 on ft1.id = fp1.post_topic
LEFT JOIN forum_categories AS fc1 on fc1.id = ft1.topic_cat
GROUP BY fc1.id
ORDER BY fp1.id ASC;

But this does not return the results I'm looking for. The problem is in trying to get the newest post for each category and the associate topic for that post.

Here is the DB structure for each table:

forum_categories

+-----------------+---------------------+------+-----+---------+----------------+
| Field           | Type                | Null | Key | Default | Extra          |
+-----------------+---------------------+------+-----+---------+----------------+
| id              | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| cat_name        | varchar(255)        | NO   | UNI | NULL    |                |
| cat_description | varchar(500)        | NO   |     | NULL    |                |
| cat_views       | bigint(20) unsigned | YES  |     | 0       |                |
| status          | tinyint(1)          | NO   |     | 1       |                |
+-----------------+---------------------+------+-----+---------+----------------+

forum_topics

+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| topic_subject | varchar(255)        | NO   |     | NULL    |                |
| topic_date    | datetime            | NO   |     | NULL    |                |
| topic_cat     | bigint(20) unsigned | NO   | MUL | NULL    |                |
| topic_by      | bigint(20) unsigned | NO   | MUL | NULL    |                |
| topic_views   | bigint(20) unsigned | YES  |     | 0       |                |
+---------------+---------------------+------+-----+---------+----------------+

forum_posts

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| id           | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| post_content | text                | NO   |     | NULL    |                |
| post_date    | datetime            | NO   |     | NULL    |                |
| post_topic   | bigint(20) unsigned | NO   | MUL | NULL    |                |
| post_by      | bigint(20) unsigned | NO   | MUL | NULL    |                |
+--------------+---------------------+------+-----+---------+----------------+

users

+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| id        | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| user_type | varchar(50)         | YES  |     | NULL    |                |
| email     | varchar(255)        | NO   | UNI | NULL    |                |
| username  | varchar(255)        | YES  | UNI | NULL    |                |
| password  | char(60)            | NO   |     | NULL    |                |
| image     | text                | YES  |     | NULL    |                |
| status    | tinyint(1)          | NO   |     | 1       |                |
+-----------+---------------------+------+-----+---------+----------------+

Here is an image of the output I'm trying to achieve. "Categories" shows the data from the forum_categories table and under "Recent" is the user, post and topic data for the latest post:

The output I'm trying to achieve

Please help me out. Thank you.

Caleb Jacobo
  • 189
  • 2
  • 12
  • sounds like you want to find the `max` id from the posts table, then join that to the other tables to get the rest of the info – pala_ May 05 '15 at 07:01
  • If I get the max(post_id) for the posts then join the other tables, would I be able to output it in the way shown in the example image added to my post, or would it only return one record? I need the max(post_id) for each category. – Caleb Jacobo May 05 '15 at 08:03
  • yeah you need to join a few times – pala_ May 05 '15 at 08:34

1 Answers1

3

While it's simple enough to join all the tables together to work out the topic, category and user for each post, you also need one additional step - you need to join to a subquery that retrieves the max(post_id) per category.

Here's one way you can do that:

select fc.cat_name, fc.cat_description, fc.cat_views, u.username, fp.post_date, ft.topic_subject
  from forum_categories fc
    inner join forum_topics ft
      on fc.id = ft.topic_cat
    inner join forum_posts fp
      on fp.post_topic = ft.id
    inner join users u
      on fp.post_by = u.id
    inner join (
      select topic_cat, max(fp.id) most_recent_post
        from forum_topics ft
          inner join forum_posts fp
            on fp.post_topic = ft.id
      group by topic_cat
    ) q
      on q.topic_cat = ft.topic_cat
        and fp.id = q.most_recent_post;

There's a demo you can play with here: http://sqlfiddle.com/#!9/3736b/1

pala_
  • 8,901
  • 1
  • 15
  • 32