[firebase-br] Store procedure x Somar campos do tipo time e resultar em horas, minutos e segundos

Sandro Souza escovadordebits em gmail.com
Qui Set 17 16:39:24 -03 2009


Bom dia/tarde Arlei.

Grande Arlei, aqui vai a minha humilde sugestão, e acredito que os outros
participantes já devam ter soluções melhores e mais inteligentes.

Minha sugestão usa apenas recursos nativos do Firebird, sem qualquer UDF
para não prender a sua base de dados a uma plataforma específica.

Criei aqui uma tabela de teste, com um campo do tipo TIME, e ao tentar
calcular o somatório dos valores que eu inseri nessa tabela, também obtive
uma mensagem de erro informando que esse tipo de operação (somatório com
campos do tipo TIME) não é permitido.

Dessa forma, modifiquei o meu somatório para que convertesse um valor do
tipo TIME em um BIGINT, decompondo o TIME em suas 3 partes (hora, minuto e
segundo) e juntando esses 3 valores em uma fórmula simples, que me resulta o
valor do TIME em segundos, ou seja, algo parecido com o seguinte:

SELECT SUM(CAST(((EXTRACT(HOUR FROM CAMPOHORA) * 60) + EXTRACT(MINUTE FROM
CAMPOHORA) * 60) + EXTRACT(SECOND FROM CAMPOHORA))AS BIGINT) FROM TESTE;

Dessa forma, obtemos um valor do tipo BIGINT (um Int64 do Delphi), que tem
todos os segundos somados.

Mas como calcular o tempo, humanamente legível, baseado na quantidade total
de segundos?

Fiz uma stored procedure que me retorna um VARCHAR(20) contendo a
"descrição" desse tempo, e ela é a seguinte:

SET TERM ^ ;

CREATE OR ALTER PROCEDURE SEGUNDOS_PARA_TEXTO(
  -- Quantidade total de segundos a ser decodificado.
  SEGUNDOS BIGINT
)RETURNS(
  -- Texto representando a quantidade de segundos informada.
  RESULTADO VARCHAR(20)
)AS
DECLARE VARIABLE QUOCIENTE BIGINT;
BEGIN
  -- Sem valor?
  IF (SEGUNDOS IS NULL) THEN
    -- Sem resultado também.
    RESULTADO = NULL;
  ELSE
  BEGIN
    -- Calcula e concatena a quantidade de horas.
    QUOCIENTE = TRUNC(SEGUNDOS / 3600);
    RESULTADO = LPAD(QUOCIENTE, 2, '0');
    SEGUNDOS  = SEGUNDOS - (QUOCIENTE * 3600);
    -- Calcula e concatena a quantidade de minutos.
    QUOCIENTE = TRUNC(SEGUNDOS / 60);
    RESULTADO = RESULTADO || ':' || LPAD(QUOCIENTE, 2, '0');
    SEGUNDOS  = SEGUNDOS - (QUOCIENTE * 60);
    -- Concatena a quantidade de segundos.
    RESULTADO = RESULTADO || ':' || LPAD(SEGUNDOS, 2, '0');
  END -- ELSE
  -- Envia o resultado.
  SUSPEND;
END^

SET TERM ; ^

Dessa forma, podemos agora juntar tudo em um SELECT:

SELECT (SELECT RESULTADO FROM SEGUNDOS_PARA_TEXTO(SUM(((EXTRACT(HOUR FROM
CAMPOHORA) * 60) + EXTRACT(MINUTE FROM CAMPOHORA) * 60) + EXTRACT(SECOND
FROM CAMPOHORA)))) FROM TESTE;

Dessa forma eu consegui o resultado esperado.

Os outros participantes devem ter soluções mas eficazes que essa, mas foi o
que me ocorreu nesse momento.

No dia em que for possível somar ou subtrair campos do tipo TIME, tudo isso
já não será mais necessário.

Espero ter ajudado mais que atrapalhado. :D

2009/9/17 Arlei F. Farnetani Junior <junior em farsoft.com.br>

> Pessoal, preciso fazer uma coisa dificil aqui...mas acredito
> que alguem já passou por isso...e pode me ajudar:
>
> Preciso pegar por exemplo uma tabela que contem
> os campos horas no formato time:
>
> TECNICO:  HORA_INICIAL:  HORA_FINAL:   TOTAL:
> DIEGO        13:00:00                 13:30:00               00:30:00
>
> Preciso fazer com que o select me resulte
> o total no formato: HHHHH:MM:SS
>
> Alguem já passou por isso?
>
>
>
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
> Para saber como gerenciar/excluir seu cadastro na lista, use:
> http://www.firebase.com.br/fb/artigo.php?id=1107
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>



Mais detalhes sobre a lista de discussão lista