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は連続して送信されたため、グループ化されています。「アクション」テーブルは参照であり、postidとposttypeだけでなく、連続したグループ化にも使用する必要があります。

私はSOを見回しましたが、私のようなものは見当たりませんでした。助けてくれてありがとう。

4

2 に答える 2

5

これは、MySQL変数で動作し、3レベルのネストを必要としない別のバージョンです。最初のレコードは、postIDとDateの順にレコードを事前に並べ替え、Post ID、タイプ、アクションのいずれかで値が変更されるたびに、グループごとに連番を割り当てます。それから、それは単純なグループです...レコードバージョンTとT2とT3を比較しません... 4つまたは5つの基準が必要な場合はどうなりますか...さらに多くのエントリをネストする必要がありますか?比較テストへの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)as Titles、

少なくともこれにより、DISTINCTタイトルが連結されます...すべての基準ごとに最大クエリ日付と他の要素を使用してその最大日付に関連付けられた1つのタイトルを取得することにより、このクエリ全体をもう1つのレベルにネストせずに、許可するのははるかに困難になります。

于 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 に答える