返回具有特定 MAX(字段) 的 group by 后的记录

发布于 2024-11-06 02:18:36 字数 2541 浏览 0 评论 0原文

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

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 ;相反,我想返回带有 MAX 字段的整行(例如通讯作者)。

所以我应该返回的,简而言之,是:

  1. 每个类别的标题; *(目前有效)
  2. 该类别的主题数量; (目前有效)
  3. 该类别的所有主题的回复数量; (这里还有另一个条件,如您所见,该回复的计数器是通过提交的原始=0的消息获取的)(目前有效)
  4. 最后一条消息的作者/数据对于该类别(这里有问题:它仅正确返回日期,而不返回作者);
  5. 一个标志,指示是否有 userA 尚未检查的任何主题; (目前也有效:如果 SUM 返回大于 0 的值,则有一个主题未查看)
  6. 该查询应该尽可能快,因为表可能非常大;

有关详细信息,这些是我的实际表格:

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;

希望有人可以帮助我!

I search on SO many topics like this, but I can't apply to my query.
This is :

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

It works: the only problem is that return only the field forum_messages.date with MAX data; intead, I'd like to return the whole row with that MAX field (so the corrispondent author, for example).

So what I should return, in less words, is :

  1. the title for each category; *(at the moment this works)
  2. the number of the topics for that category; (at the moment this works)
  3. the number of replies for all topics for that category; (here there is another condition as you can see, the counter of that replies is get by the message with the filed original=0) (at the moment this works)
  4. the author/data for the last message for that category (HERE there is the problem : it return correctly only the date, not the author);
  5. a flag that indicate if there is any topic that userA haven't been checked yet; (also at the moment works: if SUM return somethings more high than 0, there is a topic not viewed)
  6. this query is supposted to be as faster as possible, because the tables could be very big;

For details, these are my actual tables :

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;

Hope that someone can help me!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鸵鸟症 2024-11-13 02:18:36

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

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

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

We can use the query from your previous question to get the message author and the message date, and the query above to get the counters (topics and replies), and join them together:

EDIT: This query works (tested). BUT it got a little complex and has 2 subqueries in it, so I hope someone else posts a better simpler one. If the DB gets very big, this one may get sluggish.

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
女中豪杰 2024-11-13 02:18:36

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

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 不仅仅是一个日期,而是一个时间戳,并且没有两条消息可以绝对共享相同的时间戳。

To supplement the current output with the missing data, I would probably go like this:

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

Of course, this assumes that forum_messages.date is not just a date, but a timestamp and that no two messages can share absolutely the same timestamp.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文