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

Comment les sous-groupes peuvent-ils avoir une colonne d'incrémentation générée ajoutée dans une requête sql ?

Je l'ai résolu, grâce à l'aide d'un excellent article de blog ici :http://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/

La solution n'est pas triviale, nécessitant des variables et une connaissance avancée de la façon dont mysql ordonne ses opérations de requête, mais elle semble être assez performante. L'une des clés est que les affectations de variables peuvent être masquées dans les appels de fonction !

Essentiellement, la requête suivante résout le problème :

SET @num := 0, @type := '';

SELECT name, subgroup, @num AS increment
FROM table_name
WHERE 0 <= GREATEST(
   @num := IF(@type = subgroup, @num + 1, 1),
   LEAST(0, LENGTH(@type := subgroup)))

Les fonctions GREATEST , LEAST , et LENGTH sont juste là en tant que conteneurs pour les affectations de variables. Comme vous pouvez le voir, ces fonctions ne font essentiellement rien pour affecter la sortie de la requête.

Cependant, j'ai également constaté que j'avais des valeurs de "sous-groupes" dans mon tableau qui n'étaient pas consécutives. Par exemple :

+------+----------+
| name | subgroup |
+------+----------+
| john | 1        |
| doe  | 1        |
| jim  | 1        |
| greg | 2        |
| boe  | 2        |
| amos | 3        |
| ben  | 1        |
| gary | 2        |
+------+----------+

A résulté en une table de sortie comme ceci :

+------+----------+-----------+
| name | subgroup | increment |
+------+----------+-----------+
| john | 1        |         1 |
| doe  | 1        |         2 |
| jim  | 1        |         3 |
| greg | 2        |         1 |
| boe  | 2        |         2 |
| amos | 3        |         1 |
| ben  | 1        |         1 |
| gary | 2        |         1 |
+------+----------+-----------+

Suivi d'un ORDER BY la clause à la fin de la requête ne fonctionnait pas à cause de l'ordre d'exécution et masquait les affectations de variables dans le ORDER BY clause s'est rapprochée mais avait ses propres problèmes, voici donc la requête finale que j'ai utilisée :

SET @num := 0, @type := '';

SELECT name, subgroup, @num AS increment
FROM (SELECT * FROM table_name ORDER BY subgroup) AS table_name2
WHERE 0 <= GREATEST(
   @num := IF(@type = subgroup, @num + 1, 1),
   LEAST(0, LENGTH(@type := subgroup)))

Résultant en la sortie suivante :

+------+----------+-----------+
| name | subgroup | increment |
+------+----------+-----------+
| john | 1        |         1 |
| doe  | 1        |         2 |
| jim  | 1        |         3 |
| ben  | 1        |         4 |
| greg | 2        |         1 |
| boe  | 2        |         2 |
| gary | 2        |         3 |
| amos | 3        |         1 |
+------+----------+-----------+

Youpi !