我走到了尽头。 SQL Query获取最后回复的用户名和时间戳

时间:2017-05-04 03:57:55

标签: mysql sql greatest-n-per-group

这是我试图开始工作的查询。

SELECT  
    t.id AS topic_id,
    t.title AS topic_title,
    t.content AS topic_content,
    t.created_at AS topic_created_at,
    t.updated_at AS topic_updated_at,
    t.user_id AS topic_user_id,
    c.id AS comment_id,
    c.content AS comment_content,
    c.created_at AS comment_created_at,
    max_c.username AS comment_username,
    u.username AS topic_username
FROM   
    topics t
JOIN 
    (SELECT 
         c2.topic_id, c2.created_at, u2.username 
     FROM 
         comments c2
     JOIN 
         users u2 ON c2.user_id = u2.id
     JOIN 
         topics t2 ON c2.topic_id = t2.id
     ORDER BY 
         c2.created_at desc) max_c ON t.id = max_c.topic_id
JOIN 
    comments c ON max_c.created_at = c.created_at
JOIN 
    users u ON u.id = t.user_id
ORDER BY 
    c.created_at DESC

非常肯定这部分查询不正确:

SELECT 
    c2.topic_id, c2.created_at, u2.username 
FROM 
    comments c2
JOIN 
    users u2 ON c2.user_id = u2.id
JOIN 
    topics t2 ON c2.topic_id = t2.id
ORDER BY 
    c2.created_at desc

该查询当前显示以下内容。但是我希望按created_at分组,或者什么是合适的,所以我们只收到有关主题的最新回复。

如果你能提供帮助,这将是惊人的,到目前为止,我花了大约5个小时写这篇文章......

我已经在下面附加了我的表格迁移。

# Dump of table comments
# ------------------------------------------------------------

CREATE TABLE `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `content` varchar(255) DEFAULT NULL,
  `user_id` int(11) NOT NULL,
  `topic_id` int(11) DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `comments_ibfk_2` (`topic_id`),
  CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
  CONSTRAINT `comments_ibfk_2` FOREIGN KEY (`topic_id`) REFERENCES `topics` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



# Dump of table topics
# ------------------------------------------------------------

CREATE TABLE `topics` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `content` text,
  `user_id` int(11) NOT NULL,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  CONSTRAINT `topics_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



# Dump of table users
# ------------------------------------------------------------

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT 'NOT NULL',
  `email` varchar(255) DEFAULT 'NOT NULL',
  `password` char(60) DEFAULT 'NOT NULL',
  `admin` int(11) NOT NULL DEFAULT '0',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2 个答案:

答案 0 :(得分:0)

如果我理解你的问题你遇到的问题是子查询应该只返回最后一个用户名和时间戳,而是返回all。在这种情况下,你可以在订单之后使用LIMIT 1来获得所需的结果。

    SELECT c2.topic_id, c2.created_at,u2.username 
    FROM comments c2
    JOIN users u2 ON c2.user_id = u2.id
    JOIN topics t2 ON c2.topic_id = t2.id
    ORDER BY c2.created_at desc
    LIMIT 1

答案 1 :(得分:0)

请尝试以下方法......

SELECT topics.id AS topic_id,
       topics.title AS topic_title,
       topics.content AS topic_content,
       topics.created_at AS topic_created_at,
       topics.updated_at AS topic_updated_at,
       topicsUsers.user_id AS topic_user_id,
       topicsUsers.username AS topic_username,
       comments.id AS comment_id,
       comments.content AS comment_content,
       maxCreatedAt AS comment_created_at,
       commentsUsers.user_id AS comment_user_id
       commentsUsers.username AS comment_username,
FROM topics
JOIN ( SELECT topic_id AS topic_id,
              MAX( comments.created_at ) AS maxCreatedAt,
       FROM comments
       GROUP BY topic_id
     ) maxCreatedAtFinder ON topics.id = maxCreatedAtFinder.topic_id
JOIN comments ON maxCreatedAtFinder.maxCreatedAt = comments.created_at
             AND maxCreatedAtFinder.topic_id = topics.id
JOIN users AS topicsUsers ON users.id = topics.user_id
JOIN users AS commentsUsers ON users.id = comments.user_id
ORDER BY maxCreatedAt DESC

我从您的问题中可以看出,您正在寻找一个列表,其中显示了每个topic的详细信息(包括发起user user的详细信息Topic 1}})以及comment的最新Topic以及发布user的{​​{1}}的详细信息。

我的陈述遵循与您提供的陈述类似的结构。我已将commentJOIN移至topics,因为topic_idtopics中我们想要子查询的唯一详细信息,而topic_id也可以可以从comments获得。

获取为user发布最新comment的{​​{1}}的详细信息会使分组变得复杂,导致执行的联接比我们加入Topic时更多到子查询之外的Comments。所有子查询确实需要为每个Users获取created_at的最新值。因此,我已将Topic移至JOIN以及相关的字段选择。

在主要声明中,我将子查询的Users保持为INNER JOIN,这有效地将topics的{​​{1}}的最大值附加到created_at的相应记录中{1}}。

然后,我获取结果数据集并将其加入comments,以使topics及其comments的{​​{1}}的最近值topic具有内容每个created_atcomments 附加comment值的topic。请注意,虽然不太可能同时创建属于created_at的{​​{1}}个comments,因此topic的值相同。这两个记录都将连接到正在形成的数据集。在没有相反指示的情况下,我认为这是期望的行为并允许它。

然后我将结果数据集和created_at带到两个JOIN个实例,一个基于users,另一个基于topic_id user_id 1}}。这样可以在我们的数据集中为每个记录添加commentuser详细信息,其中user创建了Topicuser user的详细信息( s)谁发布了最新的comment

然后将最终数据集按时间顺序排序,从最近的记录开始。

然后选择所需的字段并由语句返回。

如果您有任何问题或意见,请随时发表评论。