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

MySQLテーブルのランクを更新します

    1つのオプションは、次のようなランキング変数を使用することです。

    UPDATE   player
    JOIN     (SELECT    p.playerID,
                        @curRank := @curRank + 1 AS rank
              FROM      player p
              JOIN      (SELECT @curRank := 0) r
              ORDER BY  p.points DESC
             ) ranks ON (ranks.playerID = player.playerID)
    SET      player.rank = ranks.rank;
    

    JOIN (SELECT @curRank := 0) 一部では、個別のSETを必要とせずに変数の初期化が可能です。 コマンド。

    このトピックに関する詳細情報:

    テストケース:

    CREATE TABLE player (
       playerID int,
       points int,
       rank int
    );
    
    INSERT INTO player VALUES (1, 150, NULL);
    INSERT INTO player VALUES (2, 100, NULL);
    INSERT INTO player VALUES (3, 250, NULL);
    INSERT INTO player VALUES (4, 200, NULL);
    INSERT INTO player VALUES (5, 175, NULL);
    
    UPDATE   player
    JOIN     (SELECT    p.playerID,
                        @curRank := @curRank + 1 AS rank
              FROM      player p
              JOIN      (SELECT @curRank := 0) r
              ORDER BY  p.points DESC
             ) ranks ON (ranks.playerID = player.playerID)
    SET      player.rank = ranks.rank;
    

    結果:

    SELECT * FROM player ORDER BY rank;
    
    +----------+--------+------+
    | playerID | points | rank |
    +----------+--------+------+
    |        3 |    250 |    1 |
    |        4 |    200 |    2 |
    |        5 |    175 |    3 |
    |        1 |    150 |    4 |
    |        2 |    100 |    5 |
    +----------+--------+------+
    5 rows in set (0.00 sec)
    

    更新: 同じランクを共有するにはタイが必要であることに気づきました。これは少し注意が必要ですが、さらに多くの変数で解決できます:

    UPDATE   player
    JOIN     (SELECT    p.playerID,
                        IF(@lastPoint <> p.points, 
                           @curRank := @curRank + 1, 
                           @curRank)  AS rank,
                        @lastPoint := p.points
              FROM      player p
              JOIN      (SELECT @curRank := 0, @lastPoint := 0) r
              ORDER BY  p.points DESC
             ) ranks ON (ranks.playerID = player.playerID)
    SET      player.rank = ranks.rank;
    

    テストケースとして、175ポイントの別のプレーヤーを追加しましょう:

    INSERT INTO player VALUES (6, 175, NULL);
    

    結果:

    SELECT * FROM player ORDER BY rank;
    
    +----------+--------+------+
    | playerID | points | rank |
    +----------+--------+------+
    |        3 |    250 |    1 |
    |        4 |    200 |    2 |
    |        5 |    175 |    3 |
    |        6 |    175 |    3 |
    |        1 |    150 |    4 |
    |        2 |    100 |    5 |
    +----------+--------+------+
    6 rows in set (0.00 sec)
    

    また、同点の場合にランクをスキップする必要がある場合は、別のIFを追加できます。 状態:

    UPDATE   player
    JOIN     (SELECT    p.playerID,
                        IF(@lastPoint <> p.points, 
                           @curRank := @curRank + 1, 
                           @curRank)  AS rank,
                        IF(@lastPoint = p.points, 
                           @curRank := @curRank + 1, 
                           @curRank),
                        @lastPoint := p.points
              FROM      player p
              JOIN      (SELECT @curRank := 0, @lastPoint := 0) r
              ORDER BY  p.points DESC
             ) ranks ON (ranks.playerID = player.playerID)
    SET      player.rank = ranks.rank;
    

    結果:

    SELECT * FROM player ORDER BY rank;
    
    +----------+--------+------+
    | playerID | points | rank |
    +----------+--------+------+
    |        3 |    250 |    1 |
    |        4 |    200 |    2 |
    |        5 |    175 |    3 |
    |        6 |    175 |    3 |
    |        1 |    150 |    5 |
    |        2 |    100 |    6 |
    +----------+--------+------+
    6 rows in set (0.00 sec)
    

    注:私が提案しているクエリはさらに簡略化できることを考慮してください。



    1. ツリートラバーサルアルゴリズムに基づいて、この結果セットからツリービューを生成するにはどうすればよいですか?

    2. com.mysql.jdbc.PacketTooBigException

    3. CASTとIsNumeric

    4. SQLite LIKE