【问题标题】:Forum MySQL queries论坛 MySQL 查询
【发布时间】:2014-02-04 08:15:24
【问题描述】:

我正在使用 CodeIgniter 构建一个基本论坛,但在处理两个 MySQL 查询时遇到了问题。

这是我的桌子:

mysql> describe forum_posts;
+----------+------------------+------+-----+-------------------+----------------+
| Field    | Type             | Null | Key | Default           | Extra          |
+----------+------------------+------+-----+-------------------+----------------+
| id       | int(11) unsigned | NO   | PRI | NULL              | auto_increment |
| topic_id | int(11)          | YES  | MUL | NULL              |                |
| user_id  | int(11)          | YES  | MUL | NULL              |                |
| post     | text             | YES  |     | NULL              |                |
| date     | timestamp        | YES  |     | CURRENT_TIMESTAMP |                |
| ip       | varchar(15)      | YES  |     | NULL              |                |
+----------+------------------+------+-----+-------------------+----------------+
6 rows in set (0.01 sec)

mysql> describe forum_topics;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| id          | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| category_id | int(11)          | YES  | MUL | NULL    |                |
| user_id     | int(11)          | YES  | MUL | NULL    |                |
| name        | varchar(100)     | YES  |     | NULL    |                |
| importance  | tinyint(2)       | YES  |     | 0       |                |
+-------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

mysql> describe forum_categories;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50)      | YES  |     | NULL    |                |
| order | tinyint(2)       | YES  |     | 0       |                |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

1) 我想选择所有类别及其各自的最新帖子
2) 我想从 ID 为 X 的类别中选择所有主题并显示该主题的最后一篇文章。

这是我到目前为止所做的

(1):

SELECT 
    C.*,

    T.name AS topic_name, 
    T.id AS topic_id,

    P.date AS post_date

FROM forum_categories AS C

LEFT JOIN 
    (
        SELECT id, category_id, name
        FROM forum_topics
        ORDER BY id DESC
    ) 
    T ON C.id = T.category_id

LEFT JOIN 
    (
        SELECT id, topic_id, date
        FROM forum_posts
        ORDER BY DATE(date) DESC
    ) 
    P ON T.id = P.topic_id

GROUP BY C.id
ORDER BY DATE(P.date) DESC

(2):

SELECT 
    T.*, 
    P.topic_id,
    P.id AS post_id,
    P.user_id,
    P.date,
    users.username
FROM forum_topics AS T
LEFT JOIN 
    (
        SELECT id, topic_id, user_id, date
        FROM forum_posts
        ORDER BY id DESC
    )
    P ON P.topic_id = T.id
LEFT JOIN 
    users ON P.user_id = users.id
WHERE T.category_id =  '1'
GROUP BY P.topic_id
ORDER BY 
    T.id DESC,
    P.id DESC
LIMIT 10

基本上我的问题是我不能先对子查询进行排序,然后再对它们进行分组。

我也不确定这些查询是否足够有效。我正在处理子查询。他们会很慢吗?

【问题讨论】:

  • 这不会很慢。
  • 谢谢。您对我的问题有什么解决方案吗?
  • 您想要的数据布局是什么?如果这将是典型的论坛布局,那么您似乎已经完成了此操作。类别可以通过名称/id 自行进入数组。主题查询可以访问该数组,同时显示结果以查找类别。您相应地对主题查询进行排序。另外你想订购什么和分组?按发布时间 DESC 排序并按主题分组?如果这是预期的结果,这似乎是直截了当的。
  • 我正在尝试列出所有类别和其中的最新帖子。编辑:实际上,您对仅类别单独查询的建议非常好。我将不得不分别获取包含最新帖子的主题,这似乎要容易得多。谢谢!很好的建议!
  • 大多数论坛平台都没有规范化,它们的数据库结构进行了某种预缓存。原因是大多数查询显示线程列表或来自特定线程的帖子列表。例如,为了“选择所有类别及其各自的最新帖子”,您应该考虑“forum_categories”表中的“last_post_id”列。这将大大简化您的查询并提高性能。另一个常见的例子是跟踪线程中的帖子数量,而不是在每次页面加载时计算每个线程的 post_count。

标签: php mysql forum


【解决方案1】:

如果无法测试,这是我会尝试开始的一个想法。其他人可能不会这样做,但逻辑至少应该可以帮助您指明方向。我相信批评者会出来,但你知道,没有人回答这个问题,所以我想我会试着让你朝着一个方向前进!

选择 * FROM forum_categories $猫数组^^ 选择 p.*, t.* FROM forum_posts p、forum_topics t、forum_categories c WHERE t.category_id = c.id 和 p.topic_id = t.id ORDER BY c.order ASC, p.date DESC 按 t.id 分组 $postArray^^ 对于 ($x = 0; $x > $catData['name'] } 打印主题 >> $postArray[$x]['name'] 打印最新帖子>> $postArray[$x]['post'] $currentCat = $catData['id']; }

【讨论】:

    【解决方案2】:

    经过几个小时的努力,我想我找到了 (1) 的解决方案,现在找到 (2) 的解决方案会更容易。

    SELECT 
        C.id,
        C.name AS category_name,
        C.order AS category_order,
        T.*
    
    FROM forum_categories AS C
    
    LEFT JOIN 
        (
            SELECT 
                T.category_id, 
                T.id AS topic_id, 
                T.name AS topic_name,
                P.user_id,
                P.username,
                P.date
            FROM forum_topics AS T
    
            LEFT JOIN
                (
                    SELECT 
                        P2.id AS post_id,
                        P2.topic_id,
                        P2.user_id,
                        P2.date, 
                        U.username
                    FROM forum_posts AS P2
                    LEFT JOIN users AS U ON P2.user_id = U.id
                    ORDER BY P2.id DESC
                )
                P ON P.topic_id = T.id
    
            ORDER BY P.post_id DESC
        )
        T ON T.category_id = C.id
    
    GROUP BY C.id
    

    编辑:修复了 (1) 查询中的一个小错误,对于那些想要完成与我相同的人来说,这里是 (2):

    SELECT 
        T.*,
        P.*
    
    FROM forum_topics AS T
    
    LEFT JOIN 
        (
            SELECT 
                P2.id AS post_id,
                P2.topic_id, 
                P2.user_id,
                P2.date,
                U.username
            FROM forum_posts AS P2
            LEFT JOIN users U ON U.id = P2.user_id
            ORDER BY P2.id DESC 
        )
        P ON P.topic_id = T.id 
    
    WHERE T.category_id =  '1'
    GROUP BY P.topic_id
    ORDER BY P.topic_id DESC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      相关资源
      最近更新 更多