sql >> データベース >  >> RDS >> Mysql

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

    派生テーブルFROM内のサブクエリ 句)、すべての行が同じuser_idを持つようにデータを並べ替えます 値は一緒になり、game_detailに基づいて値がさらに並べ替えられます 降順。

    ここで、この結果セットを使用し、条件付きのCASE..WHENを使用します。 行番号を評価する式。これは、ループ手法のようになります(アプリケーションコードで使用します。例:PHP)。前の行の値をユーザー定義変数に格納してから、現在の行の値を前の行と照合します。最終的には、それに応じて行番号を割り当てます。

    編集: MySQLに基づく docs と@GordonLinoffの観察:

    ユーザー変数を含む式の評価の順序は定義されていません。たとえば、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      |
    

    DBFiddleで表示

    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              |
    

    DBFiddleで表示



    1. postgres JSONインデックスは、従来の正規化されたテーブルと比較して十分に効率的ですか?

    2. このJavaScriptには何が必要ですか?

    3. 異なるサーバー上の2つの異なるデータベース間でOracleスキーマをコピーまたはインポートするにはどうすればよいですか?

    4. 接続されたユーザーをOracle10gデータベーススキーマから削除する