使用特定的MAX(字段)返回分组后的记录

时间:2011-05-06 23:53:43

标签: mysql sql group-by aggregate-functions

我搜索了很多类似这样的主题,但我无法应用于我的查询。 这是:

SELECT forum_categories.title, COUNT(DISTINCT forum_topics.id) AS total_topics, 
SUM(CASE WHEN forum_messages.original=0 THEN 1 ELSE 0 END) AS total_replies, forum_messages.author, 
MAX(forum_messages.date) AS last_message, SUM(CASE WHEN r.user IS NULL THEN 1 ELSE 0 END) to_view
FROM forum_categories
JOIN forum_topics ON forum_topics.category_id=forum_categories.id 
LEFT OUTER JOIN (SELECT topic, user FROM forum_visits WHERE user='userA') r ON forum_topics.id=r.topic
JOIN forum_messages ON forum_messages.topic_id=forum_topics.id
GROUP BY forum_categories.id 
ORDER BY forum_categories.date

它有效:唯一的问题是只返回带有MAX数据的字段forum_messages.date; intead,我想用MAX字段返回整行(例如,相应的作者)。

所以我应该用更少的话来回报:

  1. 每个类别的标题; *(目前有效)
  2. 该类别的主题数量; (目前有效)
  3. 该类别所有主题的回复数量; (这里有另一个条件,你可以看到,回复的计数器是通过提交的原件= 0的消息得到的)(此时此作品)
  4. 该类别的最后一条消息的作者/数据(这里有问题:它只返回正确的日期,而不是作者);
  5. 一个标志,指示是否有任何 userA 尚未检查的主题; (目前也有效:如果SUM返回的东西超过0,则有一个主题未被查看)
  6. 这个查询被假设为尽可能快,因为表格可能非常大;
  7. 详细信息,这些是我的实际表格:

    CREATE TABLE IF NOT EXISTS `forum_categories` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `title` varchar(255) NOT NULL,
      `description` varchar(255) NOT NULL,
      `date` datetime NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
    
    CREATE TABLE IF NOT EXISTS `forum_topics` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `category_id` int(11) unsigned NOT NULL,
      `title` varchar(255) NOT NULL,
      `author` varchar(255) NOT NULL,
      `date` datetime NOT NULL,
      `view` int(11) unsigned NOT NULL default '0',
      `sticky` tinyint(11) unsigned NOT NULL default '0',
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=25 DEFAULT CHARSET=utf8;    
    
    CREATE TABLE IF NOT EXISTS `forum_messages` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `topic_id` int(11) unsigned NOT NULL,
      `author` varchar(255) NOT NULL,
      `message` mediumtext NOT NULL,
      `date` datetime NOT NULL,
      `original` tinyint(11) unsigned NOT NULL default '0',
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
    
    CREATE TABLE IF NOT EXISTS `forum_visits` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `topic` int(11) unsigned NOT NULL,
      `user` varchar(255) NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `forum_visits_unique_idx` (`topic`,`user`)
    ) ENGINE=MyISAM AUTO_INCREMENT=131 DEFAULT CHARSET=utf8;
    

    希望有人可以帮助我!

2 个答案:

答案 0 :(得分:1)

我们可以使用上一个问题中的查询来获取消息作者和消息日期,以及上面的查询以获取计数器(主题和回复),并将它们连接在一起:

编辑:此查询有效(已测试)。但它有点复杂,并且有2个子查询,所以我希望其他人发布更简单的一个。如果DB变得非常大,那么这个可能会变得迟钝。

SELECT forum_categories.title,
COUNT(DISTINCT forum_topics.id) AS total_topics,
SUM(CASE WHEN forum_messages.original=0 THEN 1 ELSE 0 END) AS total_replies,
t2.author, t2.last_message

-- first get the counters per category
FROM forum_categories
JOIN forum_topics ON forum_topics.category_id=forum_categories.id
JOIN forum_messages ON forum_messages.topic_id=forum_topics.id

-- Then join a query to get last message per category
JOIN (SELECT forum_categories.id, forum_messages.author,
     forum_messages.date AS last_message
     FROM forum_categories
     JOIN forum_topics ON forum_topics.category_id=forum_categories.id
     JOIN forum_messages ON forum_messages.topic_id=forum_topics.id
     JOIN (SELECT MAX(m.date) as date, top.category_id
          FROM forum_messages m
          JOIN forum_topics top ON m.topic_id = top.id
          GROUP BY top.category_id) as t
          ON t.category_id = forum_topics.category_id AND t.date = forum_messages.date
          GROUP BY forum_categories.id) t2
     ON t2.id = forum_categories.id

GROUP BY forum_categories.id

答案 1 :(得分:1)

为了用缺少的数据补充当前输出,我可能会这样:

SELECT
  forum_stats.*,   /* just repeat the already pulled columns (expand it if needed) */
  forum_messages.* /* and here you may actually want to be more specific as to
                       what else you would like to pull from forum_messages */
FROM (
  SELECT
    forum_categories.id AS category_id,
    forum_categories.title,
    COUNT(DISTINCT forum_topics.id) AS total_topics, 
    SUM(CASE WHEN forum_messages.original=0 THEN 1 ELSE 0 END) AS total_replies,
    MAX(forum_messages.date) AS last_message,
    SUM(CASE WHEN r.user IS NULL THEN 1 ELSE 0 END) AS to_view,
    forum_categories.date
  FROM forum_categories
    JOIN forum_topics ON forum_topics.category_id=forum_categories.id 
    LEFT OUTER JOIN (
      SELECT topic, user FROM forum_visits WHERE user='userA'
    ) r ON forum_topics.id=r.topic
    JOIN forum_messages ON forum_messages.topic_id=forum_topics.id
  GROUP BY forum_categories.id
) forum_stats
  JOIN forum_topics ON forum_topics.category_id=forum_stats.category_id
  JOIN forum_messages ON forum_messages.topic_id=forum_topics.id
    AND forum_messages.date=forum_stats.last_message
ORDER BY forum_stats.date

当然,这假设forum_messages.date不仅仅是一个日期,而是一个时间戳,并且没有两条消息可以共享完全相同的时间戳。