MySQL连续行组

时间:2012-11-09 22:52:33

标签: mysql

我有一个Feed应用程序,我试图连续分组结果。 我的表看起来像这样:

    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。

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

2 个答案:

答案 0 :(得分:3)

这是另一个与MySQL变量一起使用的版本,并且不需要3级嵌套深度。第一个按照postID和Date按顺序对记录进行预先排序,并在每个组中为每个组分配一个序号,只要其中一个值在Post ID,Type和/或action之一中发生变化。从那个,它是一个简单的组...没有比较记录版本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    

这是我的link to SQLFiddle sample

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

group_concat(不同的PreQuery.Title)作为标题,

至少这会使DISTINCT标题连同...更难以让不让这个整个查询再嵌套一个级别,通过使用最大查询日期和其他元素来获得与所有条件的最大日期相关联的一个标题。

答案 1 :(得分:1)

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

这是一个解决方案(view on 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或他们之间的行动   换句话说,组标准是一组连续条目中出现最晚的日期。

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