Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como os subgrupos podem ter uma coluna de incremento gerada adicionada em uma consulta sql?


Eu resolvi isso, graças à ajuda de um post de blog excelente aqui:http://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/

A solução não é trivial, exigindo variáveis ​​e algum conhecimento avançado de como o mysql ordena suas operações de consulta, mas parece ter um bom desempenho. Uma das chaves é que as atribuições de variáveis ​​podem ser ocultadas dentro de chamadas de função!

Essencialmente, a seguinte consulta resolve o problema:
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)))

As funções GREATEST , LEAST e LENGTH estão lá apenas como contêineres para atribuições de variáveis. Como você pode ver, essas funções essencialmente não fazem nada para afetar a saída da consulta.

No entanto, também descobri que tinha valores de "subgrupo" na minha tabela que não eram consecutivos. Por exemplo:
+------+----------+
| name | subgroup |
+------+----------+
| john | 1        |
| doe  | 1        |
| jim  | 1        |
| greg | 2        |
| boe  | 2        |
| amos | 3        |
| ben  | 1        |
| gary | 2        |
+------+----------+

Resultou em uma tabela de saída assim:
+------+----------+-----------+
| 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 |
+------+----------+-----------+

Aderindo a um ORDER BY cláusula no final da consulta não funcionou por causa da ordem de execução e ocultando as atribuições de variáveis ​​no ORDER BY cláusula se aproximou, mas teve seus próprios problemas, então aqui está a consulta final que usei:
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)))

Resultando na seguinte saída:
+------+----------+-----------+
| 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 |
+------+----------+-----------+

Yay!