Média de horas - Firebird

22/03/2023

0

Olá colegas estou precisando de pegar a média de hora em uma tabela firebird.
14:57
15:07
15:04
14:50
15:09
15:01
15:00
---------
Média: 15:01


Usando o AVG para fazer a média dá erro:
Dynamic SQL Error.
expression evaluation not supported.
Argument for AVG in dialect 3 must be numeric.

Engraçado que na função do IBexpert se eu pedir a AVG ele me mostra: AVG = 30/12/1899 15:01:30.

select
         AVG(
              (CAST(SUBSTRING(hora_chegada FROM 1 FOR 2) AS INTEGER) * 60)  +
              (CAST(SUBSTRING(hora_chegada FROM 4 FOR 2) AS INTEGER))
              )
           HorasEmMinutos

FROM   chegadas

Com esta função acima eu consigo transformar em minutos. Não sei se é o caminho.

Espero ajuda dos colegas.
Dirceu Morais

Dirceu Morais

Responder

Post mais votado

24/03/2023

uma query simples não resolve o problema?
select
   replace(
      cast(
         avg(
            (CAST(SUBSTRING(hora_chegada FROM 1 FOR 2) AS INTEGER) * 60.0)  +
            CAST(SUBSTRING(hora_chegada FROM 4 FOR 2) AS INTEGER)
         )/60.0
         as varchar(5)
      ), '.',':'
   ) media
from
   chegadas

Emerson Nascimento

Emerson Nascimento
Responder

Mais Posts

23/03/2023

Arthur Heinrich

O problema de transformar em minutos, como você fez, é que depois de calcular a média você precisa transformar em horas:minutos.

Talvez uma maneira mais fácil seja transformar a data em uma quantidade de minutos a partir de uma data fixa (data - data_fixa). Você então calcula a média de minutos e volta a somar à data fixa.

select dateadd( minute, avg( datediff( minute, hora_chegada, date '1-Jan-2023' ) ), date '1-Jan-2023' )
from chegadas
Responder

24/03/2023

Dirceu Morais

Obrigado amigo pela dica,

select dateadd( minute, avg( datediff( minute, hora_chegada, date '1-Jan-2023' ) ), date '1-Jan-2023' )
from chegadas


Mas deu erro na execução do comando.
expression evaluation not supported.
The result of DATE-TIME or TIME-DATE in DATEDIFF cannot be expressed in HOUR, MINUTE, SECOND and MILLISECOND.



Mas eu consegui resolver da seguinte maneira:

    select Cast( AVG( 
              (CAST(SUBSTRING(hora_chegada FROM 1 FOR 2) AS INTEGER) * 60)  + 
              '(CAST(SUBSTRING(hora_chegada FROM 4 FOR 2) AS INTEGER)) 
              ) as float) / 60 as Retorno
         From chegadas
      //Procuro a posição do ponto decimal   
      p := Pos(',',retorno);
     //Se não tem o ponto decimal, se não tem pq é hora cheia, exemplo: 8
      if P = 0  then
      Begin
         Hr := retorno; //Hora vai ser o resultado
         mn := 0;      //Zero minutos
      End
      else
      begin
         //encontra o total de horas do numero inteiro. Ex. se o resultado for 7,066 vai buscar 7 horas
         Hr := Copy(retorno,1,p-1);
         //Acrescenta 0 no lugar das horas e busca os decimais. Ex. Se era 7,066  os minutos vão ficar 0,066 
         Parada := '0'+Copy(retorno,p,8);
         //Transforma a string em Float 
         mn  := StrToFloatDef(Parada,0);
         //multiplico os decimais por 60 minutos e arredondo o valor. Ex. 0,066 * 60 = 3,96
         mn  := RoundTo(mn * 60,-2);
      end;
     //Transformo o resultado de hr=hora e mn=minutos em  hh:mm.
     //Acrescentando zeros ao numero inteiro.  Ex. hr=7 mn 4  em 07:04
      hm := AcrescZero(hr,2) +':'+Copy(AcrescZero(FloatToStr(mn),2),1,2);



PODE MARCAR COMO RESOLVIDO
Responder

24/03/2023

Dirceu Morais

uma query simples não resolve o problema?
select
   replace(
      cast(
         avg(
            (CAST(SUBSTRING(hora_chegada FROM 1 FOR 2) AS INTEGER) * 60.0)  +
            CAST(SUBSTRING(hora_chegada FROM 4 FOR 2) AS INTEGER)
         )/60.0
         as varchar(5)
      ), '.',':'
   ) media
from
   chegadas



Obrigado amigo, bateu na trave.

Com essa sua dica, no exemplo mencionado, o resultado dá 8:98, neste caso, teria que separar as 8h pegar os 98 minutos, e multiplicar por 60 (pq dividimos tudo por 60). Pegaria o resultado obtido, no caso 98x60=5880min, arredondando 59min, e ai trocaria os 98 por 59, ficando assim 8:59.
Em outro exemplo, que o resultado seria 10:34, teria que multiplicar 34x60=2040, trocando e arredondando, teriamos 10:20.
Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar