Pergunta

A segunda seção do esta resposta usa variáveis para criar uma soma cumulativa da outra coluna.Eu estou fazendo a mesma coisa, exceto que eu estou usando um GROUP BY instrução, e somando COUNT(*) em vez de uma coluna.Aqui é o meu código para criar um mínimo de tabela e inserir valores:

CREATE TABLE `test_group_cumulative` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `group_id` int(11) unsigned NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `test_group_cumulative` (`id`, `group_id`)
VALUES
    (1, 1),
    (2, 2),
    (3, 3);

E aqui está o código que está a falhar:

SELECT
    `group_id`,
    COUNT(*) AS `count`,
    @count_cumulative := @count_cumulative + COUNT(*) AS `count_cumulative`
FROM `test_group_cumulative` AS `tgc`
JOIN (SELECT @count_cumulative := 0) AS `_count_cumulative`
GROUP BY `group_id`
ORDER BY `id`;

Aqui está o resultado:

group_id    count   count_cumulative
1   1   1
2   1   1
3   1   1

Como você pode ver, count_cumulative NÃO é de soma corretamente.No entanto, aqui é a parte estranha.Se eu substituir a COUNT(*) no count_cumulative com esse valor, 1, a consulta funciona corretamente.

    @count_cumulative := @count_cumulative + 1 AS `count_cumulative`

Aqui está o resultado correto:

group_id    count   count_cumulative
1   1   1
2   1   2
3   1   3

Obviamente, no meu app, haverá mais de um item em cada grupo, a fim de COUNT(*) não vai ser sempre 1.Eu sei que existem maneiras de fazer isso com associações ou subconsultas, e eu vou fazer o que se eu tenho, mas na minha mente, isso DEVE funcionar.Então por que não COUNT(*) trabalhar dentro de uma soma cumulativa?

Foi útil?

Solução

Este é um problema que muitas vezes enfrentam ao fazer uma análise de série temporal.A minha forma preferida para combater este é envolvê-la em um segundo seleccionar e introduzir o contador na última camada.E você pode adaptar essa técnica para mais complicado fluxos de dados, utilizando tabelas temporárias, se reqiured.

Eu fiz este pequeno sqlfiddle usando o esquema de presente: http://sqlfiddle.com/#!2/cc97e/21

E aqui é a consulta para obter a contagem cumulativa:

SELECT
tgc.group_id, @count_cumulative := @count_cumulative + cnt as cum_cnt
FROM (
  SELECT
    group_id, COUNT(*) AS cnt
  FROM `test_group_cumulative` 
  group by group_id
  order by id) AS `tgc`, 
(SELECT @count_cumulative := 0) AS `temp_var`; 

Este é o resultado que eu recebo:

GROUP_ID    CUM_CNT
1           1
2           2
3           3

O motivo da sua tentativa não funcionou:

Quando você fizer um grupo com a variável temporária, mysql executa grupos individuais de forma independente, e no momento em que cada grupo é atribuído a variável temporária valor de corrente, que neste caso é 0.

Se você executou esta consulta:

SELECT @count_cumulative;

imediatamente após

SELECT
    `group_id`,
    COUNT(*) AS `count`,
    @count_cumulative := @count_cumulative + COUNT(*) AS `count_cumulative`
FROM `test_group_cumulative` AS `tgc`
JOIN (SELECT @count_cumulative := 0) AS `_count_cumulative`
GROUP BY `group_id`
ORDER BY `id`;

você teria o valor de 1.Para cada um dos grupos, o @count_cumulative está sendo redefinido para 0.

Daí que, na minha proposta de solução, eu contornar este problema através da geração do 'grupo-conta" primeiro e, em seguida, fazendo a acumulação.

Outras dicas

Eu concordo com o @Ashalynd, o valor de count(*) não avaliado ainda.Aqui está um pequeno experimento que eu fiz :

1.
    SELECT
        GROUP_ID,    
        @COUNTER := @COUNTER + COUNT(*)  GROUPCOUNT,
        @COUNTER COUNTER
     FROM
        TEST_GROUP_CUMULATIVE, 
        (SELECT @COUNTER := 0) R
    GROUP BY
        GROUP_ID;

-- RESULT
============

   GROUP_ID    GROUPCOUNT    COUNTER
  ------------------------------------     
   1           1             0
   2           1             0
   3           1             0

2.
    SELECT @COUNTER;

    -- RESULT
    =============

    @COUNTER
    --------
    1

Para cada grupo de variável está sendo inicializado como 0.Isso significa COUNT(*) não foi avaliado ainda.

Além disso, quando você fizer:

 1.
    SELECT
        GROUP_ID,    
        @COUNTER := @COUNTER + 1  GROUPCOUNT,
        @COUNTER COUNTER
     FROM
        TEST_GROUP_CUMULATIVE, 
        (SELECT @COUNTER := 0) R
    GROUP BY
        GROUP_ID;

-- RESULT
============
   GROUP_ID    GROUPCOUNT    COUNTER
  ------------------------------------     
   1           1             1
   2           1             2
   3           1             3

2.    
SELECT @COUNTER;

    -- RESULT
    =============

    @COUNTER
    --------
    3

Ele não tem como avaliar 1.Diretamente resume e dá-lhe a soma cumulativa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top