0

协同点火器;活动记录类

从那个主题中,我问了一个关于 CodeIgniter 的问题,我想现在完全原始地做它。

这是我当前的查询。

 SELECT `forums`.*, 
        Count(topics.id) threads, 
        Count(replies.id) replies, 
        `users`.`url` user_url, 
        `users`.`name` user_name,
        `ranks`.`name` user_rank  
 FROM (`forums`)  
 LEFT JOIN `topics` ON `topics`.`f_id` = `forums`.`id`  
 LEFT JOIN `replies` ON `replies`.`t_id` = `topics`.`id`  
 LEFT JOIN `users` ON `users`.`id` = `topics`.`a_id`  
 LEFT JOIN `ranks` ON `users`.`status` = `ranks`.`id`  
 LEFT JOIN (  
 SELECT `topics`.`url` topic_url, `topics`.`name` topic_name  
 FROM `topics`  
 ORDER BY `created` DESC  
 LIMIT 1  
 ) last_post ON `topics`.`f_id` = `forums`.`id`  
 GROUP BY `forums`.`id`

所以我想做的就是把所有东西都放在一个漂亮的行里。“最后发帖者”旁边的所有内容都正常工作,如果我删除了LEFT JOIN我添加的后一个,我会得到第一个,而不是最后一个帖子。

所以我的问题是;我现在做错了什么?

另外,一个额外的问题,我之前和一个朋友谈过,他在 PHP 和 MySQL 方面比我更了解,他告诉我把它全部存储在数据库中,last_post 以及线程数和回复。

提前致谢。

更新

这是论坛表

CREATE TABLE IF NOT EXISTS `forums` (  
  `id`    int(11) NOT NULL AUTO_INCREMENT,  
  `c_id`  int(11) NOT NULL,  
  `url`   varchar(255) NOT NULL,  
  `name`  varchar(255) NOT NULL,  
  `desc`  text NOT NULL,  
PRIMARY KEY (`id`),  
KEY `url` (`url`,`name`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;  

这是主题表

CREATE TABLE IF NOT EXISTS `topics` (  
  `id` int(11) NOT NULL AUTO_INCREMENT,  
  `f_id`    int(11) NOT NULL,  
  `url`     varchar(255) NOT NULL,  
  `name`    varchar(255) NOT NULL,  
  `desc`    varchar(255) NOT NULL,  
  `body`    text NOT NULL,  
  `a_id`    int(11) NOT NULL,  
  `created` int(11) NOT NULL,  
  `edited`  int(11) NOT NULL,  
PRIMARY KEY (`id`),  
KEY `head` (`name`)  
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;

我还尝试使用降价编辑来更新它的显示方式,就像我第一次做的那样,我希望这更有吸引力。

4

1 回答 1

2

这是一个解决方案。我认为这不是最有效的解决方案,但应该可以。请注意,我将TopicsSELECT 移到了第一个 SELECT 行。

SELECT `forums`.*, 
        Count(topics.id) threads, 
        Count(replies.id) replies, 
        `users`.`url` user_url, 
        `users`.`name` user_name,
        `ranks`.`name` user_rank,
        (SELECT `topics`.`url` 
         FROM `topics` 
         WHERE `topics`.`f_id` = `forums`.`id` 
         ORDER BY `created` DESC LIMIT 1) topic_url,
        (SELECT  `topics`.`name`
         FROM `topics` 
         WHERE `topics`.`f_id` = `forums`.`id` 
         ORDER BY `created` DESC LIMIT 1) topic_name 
 FROM (`forums`) 
 LEFT JOIN `topics` ON `topics`.`f_id` = `forums`.`id`   
 LEFT JOIN `replies` ON `replies`.`t_id` = `topics`.`id`  
 LEFT JOIN `users` ON `users`.`id` = `topics`.`a_id`  
 LEFT JOIN `ranks` ON `users`.`status` = `ranks`.`id`  
 GROUP BY `forums`.`id`

可能更有效的方法

我没有数据来测试这是否更快,但这是另一种方法(我基于MySQL 中的 ROW_NUMBER()。)这带有一个附加的字符串,那就是topics表不能有重复f_idcreated组合:

SELECT `forums`.*, 
        Count(topics.id) threads, 
        Count(replies.id) replies, 
        `users`.`url` user_url, 
        `users`.`name` user_name,
        `ranks`.`name` user_rank,
        t.url topic_url,
        t.name topic_name
 FROM (`forums`)  
 LEFT JOIN (SELECT t0.id, t0.f_id, t0.url, t0.name, t0.a_id
            FROM topics AS t0
            LEFT JOIN topics AS t1 ON t0.f_id=t1.f_id AND t1.created>t0.created
            WHERE t1.id IS NULL) AS t
            ON t.f_id = forums.id
 LEFT JOIN `replies` ON `replies`.`t_id` = t.`id`  
 LEFT JOIN `users` ON `users`.`id` = t.`a_id`  
 LEFT JOIN `ranks` ON `users`.`status` = `ranks`.`id` 
 GROUP BY `forums`.`id`

试试看,先看看能不能用,再看看是不是更快。我很想收到你的回音。

于 2012-07-24T22:03:59.550 回答