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

Como somar a nova e a última entrada inserida com o mesmo ID e inserir o resultado na nova entrada

Abordagem


Você tem dois erros em sua abordagem, o que introduz complexidade.

  1. Qualquer coluna que possa ser derivada, como sua MÉDIA, deve não Ser armazenado.

    Se estiver armazenado, constitui uma coluna duplicada ... o que leva a uma anomalia de atualização, como você está enfrentando. O objetivo da Normalização é eliminar a duplicação de dados e, assim, eliminar as Anomalias de Atualização. Também elimina códigos complexos como este, bem como gatilhos, etc.

    Calcular SUM(), AVG(), etc, no conjunto de resultados somente , no vôo.

  2. Uso de colunas de ID, o que basicamente significa que você tem um sistema de arquivamento de registros, não um banco de dados relacional. Sem enumerar os muitos problemas que isso causa (eu fiz isso em outro lugar), apenas nomeando o problema aqui
    • você tem uma mentalidade de identificação.

    O ID é um ponteiro de registro físico, não fornece exclusividade de linha, conforme necessário para Bancos de Dados Relacionais.

    O ID é um ponteiro de registro físico, não significa nada, o usuário não deve vê-lo. Mas você (e outros) deu significado a isso.

    O que cola você na estrutura física do arquivo, em vez da estrutura lógica dos dados. O que por sua vez complica seu código.

    Portanto, sem fornecer um CREATE TABLE corrigido comando, deixando o seu como está, vamos fingir que o ID, e a AVERAGE, não existem no arquivo.

Um terceiro item, não relacionado à abordagem, parece que da figura dada, 10,58, você quer Quilômetros por litro, enquanto a aritmética que você detalhou (Litros por 100 Km) produzirá 9,44. Se você quer uma média de algum tipo, é melhor descobrir os elementos primeiro.

Solução

    (Code obsolete due to revision)

Pergunta revisada


Eu estava tentando obter os números que você deu, enquanto a pergunta permaneceu confusa (observe os comentários nesse sentido). Como você tem Revisado sua pergunta, o requisito agora está claro. Agora parece que você quer (a) Litros por 100 Km [ainda não é uma "média"], e (b) um valor geral para cada recorde [uma espécie de total em execução]. Nesse caso, use este código.

As notas acima permanecem válidas e aplicáveis.
    SELECT  CARID,
            DATETIME,
            KM,
            LI,
            LPCK = ( LI_TOT / ( ( KM_LAST-KM_FIRST / 100 ) )  -- not stored
        FROM (
            -- create a Derived Table with KM_FIRST
            SELECT  CARID,
                    DATETIME,
                    -- not stored
                    KM_FIRST = (
                SELECT  MIN( KM )        -- get the first KM for car
                    FROM CONSUM
                    WHERE CARID = C.CARID
                    ),
                    KM_LAST = (
                SELECT  MAX( KM )        -- get the last KM for car
                    FROM CONSUM
                    WHERE CARID = C.CARID
                    ),
                    KM,                  -- KM for this row
                    LI,                  -- LI for this row
                    LI_TOT = (
                SELECT  SUM( LI )        -- get the total LI for car
                    FROM CONSUM
                    WHERE CARID = C.CARID
                    AND KM != (          -- exclude first LI for car
                    SELECT  MIN( KM )    -- get the first KM for car
                        FROM CONSUM
                        WHERE CARID = C.CARID
                        )
                    )
                FROM CONSUM C
            ) AS CONSUM_EXT

        ORDER BY CARID,
            DATETIME

Observe que estou manipulando os dados, e apenas os dados, sem campos físicos, não devemos nos preocupar com os aspectos físicos do arquivo. Litros por 100 Km (o que você está chamando de MÉDIA) não é armazenado, e uma Anomalia de Atualização é evitada. O valor geral para cada registro é calculado "on the fly", apenas no momento da exibição.

Isso também elimina sua /first entry questão.

Claro, CARID também não tem sentido para o usuário.

Sinta-se à vontade para comentar ou fazer perguntas, etc.

Armazenamento rígido


Há muitos problemas com o armazenamento de um valor que pode ser derivado. Isso é Hard-coding no nível de armazenamento de dados. Claro, você pode usar um gatilho para aliviar a dor, mas ainda não funcionará, porque (a) o princípio está quebrado e (b) viola os princípios de engenharia existentes. Por exemplo. o que acontece quando o LI para uma única linha é inserido incorretamente (por exemplo, 700.17) e posteriormente corrigido (por exemplo, 70.17)? Todas as linhas subsequentes para esse carro agora estão incorretas e precisam ser recalculadas e atualizadas. Então agora você precisa de um gatilho de atualização, bem como um gatilho de inserção. O câncer se compõe.

O conceito de uma anomalia de atualização, a proibição de armazenar valores que podem ser derivados, está conosco desde 1970, por um bom motivo. Nós os evitamos, por um bom motivo.