进行分组以避免在其中一个值发生更改的行之间返回具有相同列值集的行

时间:2018-03-19 21:24:12

标签: mysql sql group-by row calculated-columns

我有一个包含帖子编辑消息的表,外键将错误消息与其各自的帖子和作者相关联:

post_id   author_id  edit_message                            date
1         1          "first author's first edit to post 1"   2018-03-19 12:00:00
1         1          "first author's second edit to post 1"  2018-03-19 12:05:00
2         1          "first author's first edit to post 2"   2018-03-19 12:10:00
1         1          "first author's third edit to post 1"   2018-03-19 12:15:00
1         2          "second author's first edit to post 1"  2018-03-19 12:20:00
1         1          "first author's fourth edit to post 1"  2018-03-19 12:25:00

示例数据:

CREATE TABLE IF NOT EXISTS `post_edits` (
  `post_id` int(6) unsigned NOT NULL,
  `author_id` int(3) unsigned NOT NULL,
  `edit_message` varchar(200) NOT NULL,
  `post_date` DATE NOT NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `post_edits` (`post_id`, `author_id`, `edit_message`, `post_date`) VALUES
  ("1", "1", "first author's first edit to post 1", "2018-03-19 12:00:00"),
  ("1", "1", "first author's second edit to post 1", "2018-03-19 12:05:00"),
  ("2", "1", "first author's first edit to post 2", "2018-03-19 12:10:00"),
  ("1", "1", "first author's third edit to post 1", "2018-03-19 12:15:00"),
  ("1", "2", "second author's first edit to post 1", "2018-03-19 12:20:00"),
  ("1", "1", "first author's fourth edit to post 1", "2018-03-19 12:25:00");

And SQLFiddle of same

我希望得到一个按日期排序的编辑消息列表,其分组方式是我只获得特定作者为特定帖子制作的最新编辑消息,和计数由于另一位作者编辑了该帖子或同一作者编辑了另一篇文章,因此同一篇文章和作者有多少其他编辑消息。返回的行看起来像:

post_id   author_id  edit_messag                             date                 edits_between
1         1          "first author's fourth edit to post 1"  2018-03-19 12:25:00  0
1         2          "second author's first edit to post 1"  2018-03-19 12:20:00  0
1         1          "first author's third edit to post 1"   2018-03-19 12:15:00  0
2         1          "first author's first edit to post 2"   2018-03-19 12:10:00  0
1         1          "first author's second edit to post 1"  2018-03-19 12:05:00  1

请注意,不会返回数据库中的第一行,因为第二行是同一作者对同一帖子的较新编辑。 edits_between列会计算由于此标准而未返回相同post_idauthor_id的行数。这背后的想法是我可以显示最近的编辑消息列表,如:

Latest edits:
  1. 2018-03-19 12:15:00 to post id 1: "first author's third edit"
  2. 2018-03-19 12:10:00 to post id 1: "second author's first edit"
  3. 2018-03-19 12:05:00 to post id 1: "first author's second edit" (+1 previous)

(+1 previous)附录显示已跳过一条旧邮件。

这是我到目前为止所做的事情,但是它通过邮寄父母和作者对选定的行进行分组,而不考虑不同作者在不同时间进行编辑的顺序。

SELECT post_id, MAX(post_date), author_id, COUNT(1) AS edits_between
FROM posts
GROUP BY post_id, author_id
ORDER BY post_date DESC
LIMIT 10

这看起来像:

Latest edits:
  1. 2018-03-19 to post id 1: "second author's first edit to post 1" (+1 edit)
  2. 2018-03-19 to post id 1: "first author's first edit to post 1" (+4 edits)
  3  2018-03-19 to post id 2: "first author's first edit to post 2" (+1 edit)

我想解决方案涉及某种GROUP BY has_the_author_or_post_changed子句,但我不知道如何在SQL中实现它。

1 个答案:

答案 0 :(得分:1)

如果您查看SQLFiddle查询我为您设置了

GROUP_CONCATGROUP BY结合使用可以或多或少地满足您的需求。

没有GROUP_CONCAT选项的

SEPARATOR会自动生成以逗号分隔的值

为了让您获得所需的结果,您必须执行GROUP_CONCAT才能按照您的个性化列列出一行中的多个值,如{{1}列中所示}& Posts。您将要设置的额外步骤是设置EditMessages,将多个查询连接到一个,以便他们SubQuery您希望看到的信息汇总在一起,如您所见从我的例子。

此处显示的方法不是完整的"工作"例如,你需要的是一个最小的工作"使用所需方法进行原型查询,以便最好地聚合您在指定列中加入的值。

作为此方法的说明,您可以使用:

GROUP_CONCAT

为了让您了解这些字段的内容。为了简单起见,我故意将其从下面的示例查询中删除。

SQL Fiddle SELECT GROUP_CONCAT(user_ids SEPARATOR " // ") AS User

没有用户SELECT GROUP_CONCAT(user_ids SEPARATOR " // ") AS Users

SQL Fiddle

MySQL 5.6架构设置

GROUP_CONCAT

查询1

CREATE TABLE IF NOT EXISTS post_edits (
  `posts_id` int(6) unsigned NOT NULL,
  `user_ids` int(3) unsigned NOT NULL,
  `edit_message` varchar(200) NOT NULL,
  `posts_texts` varchar(200) NOT NULL,
  `posts_date` DATE NOT NULL) DEFAULT CHARSET=utf8;
INSERT INTO post_edits (
  `posts_id`, 
  `user_ids`, 
  `edit_message`, 
  `posts_texts`, 
  `posts_date`) 
  VALUES
  ("1", "1", " First author's first edit to Post 1 ", " Author 1 Edit 1  ", "2018-03-19 12:00:00"),
  ("1", "1", " First author's second edit to Post 1 ", " Author 1 Edit 2  ", "2018-03-19 12:05:00"),
  ("2", "1", " First author's first edit to Post 2 ", " Author 1 Edit 1  ", "2018-03-19 12:10:00"),
  ("1", "1", " First author's third edit to Post 1 ", " Author 1 Edit 3  ", "2018-03-19 12:15:00"),
  ("1", "2", " Second author's first edit to Post 1 ", " Author 2 Edit 1   ", "2018-03-19 12:20:00"),
  ("1", "1", " First author's fourth edit to Post 1 ", " Author 1 Edit 4  ", "2018-03-19 12:25:00"),
  ("2", "1", " First author's second edit to Post 2 ", " Author 1 Edit 2   ", "2018-03-19 12:45:00"),
  ("2", "2", " Second author's first edit to Post 2 ", " Author 2 Edit 1  ", "2018-03-19 12:55:00"),
  ("2", "2", " Second author's second edit to Post 2 ", " Author 2 Edit 1  ", "2018-03-19 13:05:00"),
  ("1", "2", " Second author's second edit to Post 1 ", " Author 2 Edit 2  ", "2018-03-19 13:20:00");

<强> Results

SELECT posts_date, 
  posts_id, 
  user_ids,
  GROUP_CONCAT(posts_texts SEPARATOR ' //') AS Posts, 
  GROUP_CONCAT(edit_message SEPARATOR ' //') AS EditMessages,
  GROUP_CONCAT(user_ids SEPARATOR " // ") AS Users,
  COUNT(1) AS edits_between

FROM post_edits

GROUP BY posts_id, user_ids
ORDER BY posts_date DESC, user_ids