MySQL の複数の列に基づいてランクを決定する




sql-rank (3)

バージョン8.0より前のMySQLにおける最良の解決策は以下の通りです。

select gl.*, 
       (@rn := if(@lastUserId = user_id, @rn + 1,
                  if(@lastUserId := user_id, 1, 1)
                 )
        ) as user_game_rank
from (select gl.*
      from game_logs gl
      order by gl.user_id, gl.game_detail desc
     ) gl cross join
     (select @rn := 0, @lastUserId := 0) params;

順序付けは副照会で行われます。 これはMySQL 5.7以降で必要です。 変数の割り当てはすべて1つの式で行われるため、式の評価の順序が異なることは問題になりません(MySQLは式の評価の順序を保証しません)。

私は3つのフィールドを持つテーブルがあります、私はuser_idとgame_idに基づいて列をランク付けしたいです。

これはSQLフィドルです: http://sqlfiddle.com/#!9/883e9d/1 ://sqlfiddle.com/#!9/ http://sqlfiddle.com/#!9/883e9d/1

私はすでにテーブルを持っています:

 user_id | game_id |   game_detial_sum  |
 --------|---------|--------------------|
 6       | 10      |  1000              |   
 6       | 11      |  260               |
 7       | 10      |  1200              |
 7       | 11      |  500               |
 7       | 12      |  360               |
 7       | 13      |  50                | 

予想される出力:

user_id  | game_id |   game_detial_sum  |  user_game_rank  |
 --------|---------|--------------------|------------------|
 6       | 10      |  1000              |   1              |
 6       | 11      |  260               |   2              |
 7       | 10      |  1200              |   1              |
 7       | 11      |  500               |   2              |
 7       | 12      |  360               |   3              |
 7       | 13      |  50                |   4              |

これまでの私の努力:

SET @s := 0; 
SELECT user_id,game_id,game_detail, 
       CASE WHEN user_id = user_id THEN (@s:[email protected]s+1) 
            ELSE @s = 0 
       END As user_game_rank 
FROM game_logs

編集:( From OP Comments ):順序は game_detail 降順に基づいてい game_detail

game_detailの順序


非常に単純な相関副照会を使用することができます。

SELECT *, (
    SELECT COUNT(DISTINCT game_detail) + 1
    FROM game_logs AS x
    WHERE user_id = t.user_id AND game_detail > t.game_detail
) AS user_game_rank
FROM game_logs AS t
ORDER BY user_id, user_game_rank

DBフィドル

ユーザー変数よりは遅くなりますが、はるかに信頼性が高くなります。 必要なのはそれらを壊すための一つのJOINです。


SELECT user_id, game_id, game_detail, 
       CASE WHEN user_id = @lastUserId 
            THEN @rank := @rank + 1 
            ELSE @rank := 1 
       END As user_game_rank,
       @lastUserId := user_id
FROM game_logs
cross join (select @rank := 0, @lastUserId := 0) r
order by user_id, game_detail desc

SQLFiddleデモ





sql-rank