4

我有一个提要应用程序,我正在尝试对结果进行连续分组。我的表如下所示:

    postid | posttype | target | action     |        date         | title      | content
      1    |  userid  |  NULL  | upgrade    | 0000-01-00 00:00:00 | Upgraded 1 | exmple
      1    |  userid  |  NULL  | upgrade    | 0000-01-00 00:00:01 | Upgraded 2 | exmple
      1    |  userid  |  NULL  | downgrade  | 0000-01-00 00:00:02 | Downgraded | exmple
      1    |  userid  |  NULL  | upgrade    | 0000-01-00 00:00:03 | Upgraded   | exmple

我希望的结果是:

    postid | posttype | target | action     |        date         | title      | content
      1    |  userid  |  NULL  | upgrade    | 0000-01-00 00:00:01 | Upgrade 1  | exmple,exmple
      1    |  userid  |  NULL  | downgrade  | 0000-01-00 00:00:02 | Downgraded | exmple
      1    |  userid  |  NULL  | upgrade    | 0000-01-00 00:00:03 | Upgraded   | exmple

如您所见,因为升级 1 和升级 2 是连续发送的,所以它将它们组合在一起。“Action”表是一个参考,应该用于连续分组以及 postid 和 posttype。

我环顾四周,但没有看到任何像我这样的东西。提前感谢您的帮助。

4

2 回答 2

5

这是另一个与 MySQL 变量一起使用且不需要 3 级嵌套深度的版本。第一个按 postID 和 Date 按顺序对记录进行预排序,并在 Post ID、Type 和/或操作中的任何一个值发生变化时为每个组分配一个序号。从那开始,它是一个简单的分组...没有将记录版本 T 与 T2 到 T3 进行比较...如果您想要 4 或 5 个标准怎么办...您是否需要嵌套更多条目?或者只是添加 2 个更多 @ sql变量比较测试...

您的呼叫效率更高...

select
      PreQuery.postID,
      PreQuery.PostType,
      PreQuery.Target,
      PreQuery.Action,
      PreQuery.Title,
      min( PreQuery.Date ) as FirstActionDate,
      max( PreQuery.Date ) as LastActionDate,
      count(*) as ActionEntries,
      group_concat( PreQuery.content ) as Content
   from
      ( select
              t.*,
              @lastSeq := if( t.action = @lastAction
                          AND t.postID = @lastPostID
                          AND t.postType = @lastPostType, @lastSeq, @lastSeq +1 ) as ActionSeq,
              @lastAction := t.action,
              @lastPostID := t.postID,
              @lastPostType := t.PostType
           from
              t,
              ( select @lastAction := ' ',
                       @lastPostID := 0,
                       @lastPostType := ' ',
                       @lastSeq := 0 ) sqlVars
           order by
              t.postid,
              t.date ) PreQuery
   group by
      PreQuery.postID,
      PreQuery.ActionSeq,
      PreQuery.PostType,
      PreQuery.Action    

这是我到 SQLFiddle 示例的链接

对于标题,您可能需要调整行...

group_concat( distinct PreQuery.Title ) 作为标题,

至少这将给 DISTINCT 标题连接......如果不通过让最大查询日期和其他元素获得与每个所有条件的最大日期相关联的一个标题,将整个查询再嵌套一层,就更难获得。

于 2012-11-10T04:38:21.247 回答
1

您的表中没有主键,因此对于我的示例,我使用了date. 您应该创建一个自动增量值并使用它而不是date在我的示例中。

这是一个解决方案(在 SQL Fiddle 上查看):

SELECT 
  postid,
  posttype,
  target,
  action,
  COALESCE((
    SELECT date
    FROM t t2
    WHERE t2.postid = t.postid
    AND t2.posttype = t.posttype
    AND t2.action = t.action
    AND t2.date > t.date
    AND NOT EXISTS (
      SELECT TRUE
      FROM t t3
      WHERE t3.date > t.date
      AND t3.date < t2.date
      AND (t3.postid != t.postid OR t3.posttype != t.posttype OR t3.action != t.action)
    )
  ), t.date) AS group_criterion,
  MAX(title),
  GROUP_CONCAT(content)
FROM t
GROUP BY 1,2,3,4,5
ORDER BY group_criterion

它基本上是这样写的:

为每一行创建一个组标准,并在最后按它分组。
此标准是当前date之后的最高行,并且与当前行具有相同的 postid、posttype 和 action,但它们之间可能没有一行不同的 postid、posttype 或 action。
换句话说,组标准是一组连续条目中出现的最高日期。

如果您使用正确的索引,它应该不会太慢,但是如果您有很多行,您应该考虑缓存这些信息。

于 2012-11-10T01:34:01.900 回答