Mysql
 sql >> Base de données >  >> RDS >> Mysql

Rang dense MySQL pour chaque groupe/partition

Vous pouvez créer un MyISAM (temporaire) table avec un rank AUTO_INCREMENT colonne dans une CLÉ PRIMAIRE composite. De cette façon, rank aura une séquence par ID lorsque vous remplissez le tableau avec un (id, item_code) distinct combinaisons. Vous pouvez ensuite joindre cette table avec les données d'origine.

CREATE TEMPORARY TABLE tmp_rank(
  id INT,
  item_code varchar(50),
  rank INT AUTO_INCREMENT,
  PRIMARY KEY (id, rank)
) engine=MyISAM
  SELECT DISTINCT NULL as rank, id, item_code
  FROM test t
  -- WHERE <several filters>
  ORDER BY id, item_code
;

SELECT t.*, x.rank
FROM tmp_rank x
JOIN test t USING(id, item_code)
-- WHERE <several filters>

Démo

Si vous le souhaitez en une seule requête, vous pouvez essayer celle-ci :

SELECT id, item_code,
    CASE 
      WHEN id = @curId AND item_code = @curCode
        THEN @curRank
      WHEN id <> @curId THEN @curRank := 1
      ELSE @curRank := @curRank + 1
    END  AS rank,
    @curId := id,
    @curCode := item_code
FROM test t
CROSS JOIN (SELECT
    @curRank := 0,
    cast(@curCode := null as signed),
    cast(@curId   := NULL as char)
) r
#WHERE <several filters>
ORDER BY id, item_code

Démo

Sachez que l'ordre d'évaluation des opérations dans une instruction SQL n'est pas défini. Ainsi, lorsque vous lisez et écrivez une variable utilisateur dans la même instruction, vous relayez les détails d'implémentation.

Dans MySQL 8 ou MariaDB 10.2 ce serait :

SELECT  id, item_code,
    DENSE_RANK() OVER (PARTITION BY id ORDER BY item_code) as `rank`
FROM test t
-- WHERE <several filters>

Démo