派生テーブル
(FROM
内のサブクエリ 句)、すべての行が同じuser_id
を持つようにデータを並べ替えます 値は一緒になり、game_detail
に基づいて値がさらに並べ替えられます 降順。
ここで、この結果セットを使用し、条件付きのCASE..WHEN
を使用します。 行番号を評価する式。これは、ループ手法のようになります(アプリケーションコードで使用します。例:PHP)。前の行の値をユーザー定義変数に格納してから、現在の行の値を前の行と照合します。最終的には、それに応じて行番号を割り当てます。
編集: MySQLに基づく
ユーザー変数を含む式の評価の順序は定義されていません。たとえば、SELECT @ a、@ a:[email protected]<という保証はありません。 / a> +1は最初に@aを評価してから、割り当てを実行します。
行番号を評価し、user_id
を割り当てる必要があります @u
への値 同じ式内の変数。
SET @r := 0, @u := 0;
SELECT
@r := CASE WHEN @u = dt.user_id
THEN @r + 1
WHEN @u := dt.user_id /* Notice := instead of = */
THEN 1
END AS user_game_rank,
dt.user_id,
dt.game_detail,
dt.game_id
FROM
( SELECT user_id, game_id, game_detail
FROM game_logs
ORDER BY user_id, game_detail DESC
) AS dt
結果
| user_game_rank | user_id | game_detail | game_id |
| -------------- | ------- | ----------- | ------- |
| 1 | 6 | 260 | 11 |
| 2 | 6 | 100 | 10 |
| 1 | 7 | 1200 | 10 |
| 2 | 7 | 500 | 11 |
| 3 | 7 | 260 | 12 |
| 4 | 7 | 50 | 13 |
MySQL ドキュメント からの興味深いメモ 、最近発見したもの:
MySQLの以前のリリースでは、SET以外のステートメントでユーザー変数に値を割り当てることができました。この機能は、下位互換性のためにMySQL 8.0でサポートされていますが、MySQLの将来のリリースで削除される可能性があります。
また、仲間のSOメンバーのおかげで、MySQLチームがこのブログに出くわしました: https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/
一般的な観察は、ORDER BY
を使用することです 同じクエリブロック内のユーザー変数の評価では、値が常に正しいことを保証するものではありません。として、MySQLオプティマイザはかもしれません 所定の位置に来て、推定を変更します 評価の順序。
この問題への最善のアプローチは、MySQL 8以降にアップグレードし、 Row_Number()
機能:
スキーマ(MySQL v8.0)
SELECT user_id,
game_id,
game_detail,
ROW_NUMBER() OVER (PARTITION BY user_id
ORDER BY game_detail DESC) AS user_game_rank
FROM game_logs
ORDER BY user_id, user_game_rank;
結果
| user_id | game_id | game_detail | user_game_rank |
| ------- | ------- | ----------- | -------------- |
| 6 | 11 | 260 | 1 |
| 6 | 10 | 100 | 2 |
| 7 | 10 | 1200 | 1 |
| 7 | 11 | 500 | 2 |
| 7 | 12 | 260 | 3 |
| 7 | 13 | 50 | 4 |