0

次の列を持つ「アクティビティ」というテーブルがあるとします。

whenItHappened 日時、誰のテキスト、どのテキスト

過去 1 時間で、最近アクティブな 10 人のユーザーによる最新の 5 つのアクションを選択したいと考えています。

これまでのところ、私は持っています:

SELECT * FROM activity
JOIN (
    SELECT who FROM activity
    WHERE whenItHappened >= (CURDATE()- INTERVAL 1 HOUR)
    GROUP BY (who)
    ORDER BY whenItHappened DESC
    LIMIT 10
) AS unique_recent_users
ON unique_recent_users.who = activity.who;

これにより、最近アクティブだった 10 人のユーザーによるすべてのアクティビティが適切に選択されます。ただし、各ユーザーの最後の 5 つのアクションだけに制限する良い方法がわかりません。

SQL ステートメントの最後に LIMIT 句を配置すると、合計 5 つの結果しか返されません。望ましい動作は、過去 1 時間にアクティブなユーザーが 10 人いた場合、最近アクティブなユーザーごとに 5 つずつ、合計 50 のアクションを表示することです。

これは、PHP を 1 つのクエリに使用して最新の 10 人のユーザーを取得し、次に各ユーザーから 5 つのアクションを取得することで簡単に実行できますが、MySQL でネイティブにこれを行うためのエレガントな方法が必要だと考えずにはいられません。

編集: (Darrrren のリンク経由で、すべてのユーザーから最新の 5 つのアクションを選択できるこのソリューションを見つけました。テーブルが大きくなると、パフォーマンスがどのようになるかわかりません。)

select whenItHappened, who, what
from activity
where (
   select count(*) from activity as a
   where a.who = activity.who and a.whenItHappened <= activity.whenItHappened
) <= 5;
4

1 に答える 1

0

MySQLでこれをエレガントに行う方法はありません。動作する1つの方法には、自己参加が必要です。

select a.*
from (SELECT who
      FROM activity
      WHERE whenItHappened >= (CURDATE()- INTERVAL 1 HOUR)
      GROUP BY (who)
      ORDER BY whenItHappened DESC
      LIMIT 10
     ) AS unique_recent_users join
     Activity a
     on unique_recent_users.who = activity.who join
     Activity a2
     on a2.who = a.who and
        a2.whenItHappened >= a.WhenItHappened
group by a.id
having count(*) <= 5

(これは、MySQLの非表示列の「機能」を使用して、group byステートメントに含まれていない列を返すことに注意してください。)

ユーザーごとのアクティビティテーブルにカウンターがある場合は、このカウンターを使用して最新の5つを取得できます。ユーザーに関係なく、最新の50のアクティビティが必要な場合は、それも実行できます。また、他のほとんどのデータベースを使用している場合は、ランキング関数(row_number()特に)が問題をエレガントに解決します。

于 2012-11-09T20:10:47.773 に答える