Array
(
)

Banco Firebird (Problemas ao retornar apenas o primeiro registro)

João Cristo
   - 03 set 2015

Bom dia Prezados,
Estou tentando retornar apenas o maior registro do ORDXFUN na consulta abaixo, porém não estou conseguindo, vocês poderiam me ajudar?
select
ORDSERV.TAG AS OS, ORDSERV.DATPRO2 AS DATA,
USER_ANALIS.U_DESCRICA AS ANALISE,
MAX (ORDXFUN.DATHORFIM) AS DATHORFIM

from ORDSERV
inner join USER_ANALIS on ORDSERV.R_USER_ANALIS_U_PK_REDUZIDO=USER_ANALIS.U_PK_REDUZIDO
inner join ORDXFUN ON ORDXFUN.CODEMP=ORDSERV.CODEMP AND ORDXFUN.CODORD=ORDSERV.CODORD
WHERE ORDSERV.STATORD = 'A'
GROUP BY ORDSERV.TAG, ORDSERV.DATPRO2, USER_ANALIS.U_DESCRICA, ORDXFUN.DATHORFIM
Retorno:
Clique na imagem para abrir em uma nova janela

Fabio Basso
|
MVP
Pontos: 105
    03 set 2015

create table teste_data (
id_teste_data integer not null,
datahora timestamp,
data date,
primary key (id_teste_data));

insert into teste_data values (1, '09/03/2015 10:00:00', '09/03/2015');
insert into teste_data values (2, '09/03/2015 11:00:00', '09/03/2015');
insert into teste_data values (3, '09/03/2015 12:00:00', '09/03/2015');
insert into teste_data values (4, '09/04/2015 10:01:00', '09/04/2015');
insert into teste_data values (5, '09/04/2015 10:01:01', '09/04/2015');
insert into teste_data values (6, '09/04/2015 10:01:02', '09/04/2015');

select * from teste_data;
select data, max(datahora)
from teste_data
group by data;

Neste exemplo acima, o resultado será sempre a última hora, agrupado por dia.

No exemplo que vc mandou, foi agrupado pelo campo ORDXFUN.DATHORFIM , e eu acho que este campo está armazenando data e hora, então ele não vai apenas um horário, pois não está agrupado apenas pelo dia.

João Cristo
   - 03 set 2015

Desculpe a ignorância Fabio, entendi a consulta pelo seu select, porém, não sei como modificar o meu para obter o resultado.

Fabio Basso
|
MVP
Pontos: 105
    03 set 2015

Tenta isso (alterei o último campo da sua cláusula group by):
select
ORDSERV.TAG AS OS, ORDSERV.DATPRO2 AS DATA,
USER_ANALIS.U_DESCRICA AS ANALISE,
MAX (ORDXFUN.DATHORFIM) AS DATHORFIM

from ORDSERV

inner join USER_ANALIS on ORDSERV.R_USER_ANALIS_U_PK_REDUZIDO=USER_ANALIS.U_PK_REDUZIDO
inner join ORDXFUN ON ORDXFUN.CODEMP=ORDSERV.CODEMP AND ORDXFUN.CODORD=ORDSERV.CODORD

WHERE ORDSERV.STATORD = 'A'
GROUP BY ORDSERV.TAG, ORDSERV.DATPRO2, USER_ANALIS.U_DESCRICA, ORDSERV.DATPRO2

João Cristo
   - 03 set 2015

Funcionou perfeitamente Fábio, porém, quando adiciono o cálculo que você tinha me ajudado não consigo retornar apenas um registro e também não consegui arredondar o tempototal com Cast.

SELECT
ORDSERV.TAG AS OS,
ORDSERV.DATPRO, MIN(ORDXFUN.DATHORINI) AS DATHORINI, MAX(ORDXFUN.DATHORFIM) AS DATHORFIM,
datediff(hour, ORDSERV.DATPRO, ORDXFUN.DATHORINI) || ':' ||mod(datediff (minute, ORDSERV.DATPRO, ORDXFUN.DATHORINI), 60) as tempototal

FROM ORDSERV
inner join USER_ANALIS on ORDSERV.R_USER_ANALIS_U_PK_REDUZIDO=USER_ANALIS.U_PK_REDUZIDO
inner join ORDXFUN ON ORDXFUN.CODEMP=ORDSERV.CODEMP AND ORDXFUN.CODORD=ORDSERV.CODORD

WHERE ORDSERV.STATORD='A'

AND ORDSERV.CODEMP=:CODEMP
GROUP BY ORDSERV.TAG, USER_ANALIS.U_DESCRICA, ORDSERV.DATPRO, ORDXFUN.DATHORFIM, ORDXFUN.DATHORINI
ORDER BY 1

Retorno:

Clique na imagem para abrir em uma nova janela

Fabio Basso
|
MVP
Pontos: 105
    03 set 2015

João,

Você está agrupando novamente por ORDXFUN.DATHORINI, vc precisa agrupar por ORDSERV.DATPRO2.

Quanto aos zeros, eu não consegui simular isso aqui. Tem como vc postar os tipos de dados dessas tabelas (O DDL das tabelas, ou seja o código fonte de criação das tabelas)?

João Cristo
   - 03 set 2015

Tentei agrupar pela ORDSERV.DATPRO2 e retornou o erro, vou verificar o código fonte mais os campos de datas são todos TIMESTAMP.

SELECT
ORDSERV.TAG AS OS,
ORDSERV.DATPRO, MIN(ORDXFUN.DATHORINI) AS DATHORINI, MAX(ORDXFUN.DATHORFIM) AS DATHORFIM,
datediff(hour, ORDSERV.DATPRO, ORDXFUN.DATHORINI) || ':' ||mod(datediff (minute, ORDSERV.DATPRO, ORDXFUN.DATHORINI), 60) as tempototal

FROM ORDSERV
inner join USER_ANALIS on ORDSERV.R_USER_ANALIS_U_PK_REDUZIDO=USER_ANALIS.U_PK_REDUZIDO
inner join ORDXFUN ON ORDXFUN.CODEMP=ORDSERV.CODEMP AND ORDXFUN.CODORD=ORDSERV.CODORD

WHERE ORDSERV.STATORD='F'

AND ORDSERV.CODEMP=:CODEMP
GROUP BY ORDSERV.TAG, ORDSERV.DATPRO2, USER_ANALIS.U_DESCRICA, ORDSERV.DATPRO2
ORDER BY 1

Retorno:

Clique na imagem para abrir em uma nova janela

João Cristo
   - 04 set 2015

Acho que não estou entendo certo o GROUP BY, não é necessário inserir todos os campos que compõe o select?

Fabio Basso
|
MVP
Pontos: 105
    04 set 2015

Não, você indica quais campos serão agrupados. Por exemplo, se eu quiser somar o total de contas a receber e agrupar por cliente, ficaria assim:
select nome_cliente, sum(contareceber.valor_pendente) as valor_pendente
from cliente join contareceber on (cliente.id_cliente = contareceber.id_cliente)
group by nome_cliente

João Cristo
   - 04 set 2015

Ok, mais quando tentei agrupar pela DATPRO2 retornou o erro:

Dynamic SQL Error
SQL error code = -104
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause)

Fabio Basso
|
MVP
Pontos: 105
    04 set 2015

Copiei as linhas abaixo do seu código:

SELECT ORDSERV.TAG AS OS, ORDSERV.DATPRO, MIN(ORDXFUN.DATHORINI) AS DATHORINI, MAX(ORDXFUN.DATHORFIM) AS DATHORFIM,
datediff(hour, ORDSERV.DATPRO, ORDXFUN.DATHORINI) || ':' ||mod(datediff (minute, ORDSERV.DATPRO, ORDXFUN.DATHORINI), 60) as tempototal

GROUP BY ORDSERV.TAG, ORDSERV.DATPRO2, USER_ANALIS.U_DESCRICA, ORDSERV.DATPRO2

O GROUP BY tem que ser na mesma sequência do select:
SELECT ORDSERV.TAG AS OS, ORDSERV.DATPRO, MIN(ORDXFUN.DATHORINI) AS DATHORINI, MAX(ORDXFUN.DATHORFIM) AS DATHORFIM,
GROUP BY ORDSERV.TAG, ORDSERV.DATPRO2, USER_ANALIS.U_DESCRICA, ORDSERV.DATPRO2

repare que o DATPRO2 não está definido no SELECT

João Cristo
   - 04 set 2015

Desculpa, fiz uma confusão com as consultas, esta abaixo é a correta. Fiz o agrupamento seguindo a ordem mas ainda retorna erro.

SELECT
ORDSERV.TAG, ORDSERV.DATPRO,
USER_ANALIS.U_DESCRICA AS ANALISE,

MIN (ORDXFUN.DATHORINI) AS DATHORINI,
MAX (ORDXFUN.DATHORFIM) AS DATHORFIM,
SUM(ORDXFUN.DATHORFIM - ORDXFUN.DATHORINI)*24 AS TOTALHORAS,
datediff(hour, ORDSERV.DATPRO, ORDXFUN.DATHORINI) || ':' ||mod(datediff (minute, ORDSERV.DATPRO, ORDXFUN.DATHORINI), 60) as tempototal

from ORDSERV

inner join USER_ANALIS on ORDSERV.R_USER_ANALIS_U_PK_REDUZIDO=USER_ANALIS.U_PK_REDUZIDO
inner join ORDXFUN ON ORDXFUN.CODEMP=ORDSERV.CODEMP AND ORDXFUN.CODORD=ORDSERV.CODORD

WHERE ORDSERV.STATORD = 'F'
GROUP BY ORDSERV.TAG, ORDSERV.DATPRO, USER_ANALIS.U_DESCRICA

Erro:

Dynamic SQL Error
SQL error code = -104
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause)

Fabio Basso
|
MVP
Pontos: 105
    04 set 2015

Acho que é por causa dessa última linha do select:
datediff(hour, ORDSERV.DATPRO, ORDXFUN.DATHORINI) || ':' ||mod(datediff (minute, ORDSERV.DATPRO, ORDXFUN.DATHORINI), 60) as tempototal

não tem nenhum código de agrupamento(SUM por exemplo) para este campo.

João Cristo
   - 04 set 2015

Ok, mais preciso da diferença de horas/minutos entre a ORDSERV.DATPRO e o menor registro da ORDXFUN, como faço ?

Fabio Basso
|
MVP
Pontos: 105
    04 set 2015

Não consigo responder isso de imediato, eu teria que fazer uns testes direto no banco também. É possível vc me mandar uma cópia do banco para eu testar?

João Cristo
   - 04 set 2015

Infelizmente meu acesso é restrito, não consigo backup ou cópia do banco. A estrutura da tabela consegui alguns campos.

Clique na imagem para abrir em uma nova janela

Clique na imagem para abrir em uma nova janela

João Cristo
   - 04 set 2015

Consegui retornar a diferença do menor valor da DATORINI, porém, o filtro interfere no valor do totalhoras por buscar apenas o menor valor.

Resultado 1 (Clique na imagem para abrir em uma nova janela)

Resultado 2 (Clique na imagem para abrir em uma nova janela)