Abordagem
Você tem dois erros em sua abordagem, o que introduz complexidade.
-
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.
-
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 umCREATE 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.