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

Chiga - Arima Informática chiga em arimainfo.com.br
Sex Set 18 16:45:42 -03 2009


tá aí o exemplo é só executar,

Abraços.

execute block
returns (
   hora_inicial_tarefa time,
   hora_final_tarefa time,
   TotalHoras_time TIME

   )
as
declare variable TotalHoras VARCHAR(9);

declare variable hora_inicial time;
declare variable hora_final time;

DECLARE VARIABLE Horas  INT;
DECLARE VARIABLE  Minutos INT;
DECLARE VARIABLE Segundos INT;
DECLARE VARIABLE TotalSegundos INT;

begin
    hora_inicial = '08:00:45'; -- hora inciial de trabalho
    hora_final = '09:00:00'; -- prazo final
    hora_inicial_tarefa = hora_inicial;
    hora_final_tarefa =  hora_final;

    TotalSegundos = hora_final - hora_inicial;
    Horas     = (TotalSegundos /60)/60;
    Minutos   = MOD((TotalSegundos /60),60);
    Segundos  = MOD(TotalSegundos,60);

    if ((Horas < 10) or (Horas = 0) ) then
        TotalHoras = '0'||CAST(Horas AS VARCHAR(2));
    ELSE
        TotalHoras = CAST(Horas as VARCHAR(3));

    TotalHoras = TotalHoras||':';

    if ((Minutos < 10) or (Minutos = 0) ) then
        TotalHoras = TotalHoras ||'0'|| CAST(Minutos as VARCHAR(2));
    else
        TotalHoras = TotalHoras||CAST(Minutos as VARCHAR(2));

    TotalHoras = TotalHoras||':';

    if ((Segundos < 10) or (Segundos = 0) ) then
        TotalHoras = TotalHoras ||'0'|| CAST(Segundos as VARCHAR(2));
    else
        TotalHoras = TotalHoras||CAST(Segundos as VARCHAR(2));

--    TotalHoras = TotalHoras;
    TotalHoras_time = CAST(TotalHoras AS time);
    SUSPEND;


end


----- Original Message ----- 
From: "Sandro Souza" <escovadordebits em gmail.com>
To: "FireBase" <lista em firebase.com.br>; "Arlei F. Farnetani Junior" 
<junior em farsoft.com.br>
Sent: Thursday, September 17, 2009 4:39 PM
Subject: Re: [firebase-br] Store procedure x Somar campos do tipo time 
eresultar em horas, minutos e segundos


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
>
______________________________________________
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