Fórum Select trazendo somente registros da última data #596735
28/08/2018
0
Estou me batendo com uma consulta com tabela referenciada, onde devo trazer somente 1 vez um material, carregando o valor dele baseado na última data de atualização dele. Adicionalmente tenho uma cláusula que diz que a data tem que ser diferente de 1o de agosto. Ou seja, quero o material, valor e data de atualização dele(imediatamente anterior a 01/08/2018).
Na tabela cl_conveniomaterialvalores tenho os códigos, que referencio o nome na tabela cl_material para trazer o nome por escrito, assim como referencio o código que está na tabela cl_conveniomaterialvalores com a referência na cl_convenios Então são três tabelas, 1 com os dados e as outras duas como referência (somente para trazer o nome ao invés do código)
O que estou tentando é o seguinte:
select max(A.data) as ULTIMAATUALIZACAO, B.nome, A.valor, C.nome as CONVENIO
from cl_conveniomaterialvalores as A, cl_materiais as B, cl_convenios as C
where A.convenio=C.handle and B.handle=A.material and A.data < '01.08.2018 00:00'
group by B.nome, a.valor, c.nome
order by max(a.data) desc
Porém não estou obtendo somente a última data, o material tem aparecido repetido, com datas diferentes.
Exemplo: de 1 material
Caneta
Datas de atualizacao: 01/08/2018, 06/05/2018, 20/03/2018
Eu queria trazer somente o resultado: Caneta - 06/05/2018, porém os resultados abaixo também tem aparecido.
Alguém tem alguma luz??
Obrigado
Diego
Curtir tópico
+ 0Post mais votado
28/08/2018
Qdo eu utilizava firebird, aquela forma que vc utilizou era mais performatico que o left join.
Mas acredito que o ideal para vc seria utilizar um subselect provavalmente.
Não sei como é o comportamento do firebird com subselects, em relação a performance e tal.
Mas basicamente a subselect vai funcionar igual o outer apply, ai vc colocar um top 1 ou first 1, nao me lembro qual eh no firebird, e um oder by desc pela data e ele vai trazer o ultimo registro que vc quer.
Imagino que ja resolva seu problema.
Se vc precisar de ultimo valor pago e ultima data, provavelmente deverá utilizar dois subselects.
Siga basicamente a mesma ideia do outer apply do exemplo que dei.
Mas vou dar uma olhada e ver se consigo montar um codigo e posto aqui para vc.
Atenciosamente,
Alex Lekao
Gostei + 2
Mais Posts
28/08/2018
Diego
select distinct max(A.data) as ULTIMAATUALIZACAO, B.nome, A.valor, C.nome as CONVENIO<br />
from cl_conveniomaterialvalores as A, cl_materiais as B, cl_convenios as C<br />
where A.convenio=C.handle and B.handle=A.material<br />
group by B.nome, a.valor, c.nome<br />
having max(A.data) < ''01.08.2018 00:00''<br />
order by max(a.data) desc<br />
<br />
Se eu coloco > que 01.08.2018 ele lista também, as datas acima, porém, não só a última, e sim todas ocorrências acima de 01.08, como 02,03,etc...
Gostei + 0
28/08/2018
Alex Lekao
Não sei se entendi bem.
Eu normalmente faço este tipo de referência, utilizando uma subselect para trazer apenas as datas que eu preciso.
Uma boa opção é utilizar o outer apply, com ele vc conseguira trazer mais de um resultado do que vc precisa; como por exemplo, ultima data, ultimo preco, etc., mas tudo dependerá de testes e tal.
Experimete assim e veja se funciona.
select
max(A.data) as ULTIMAATUALIZACAO,
mat.nome,
A.valor,
cv.nome as CONVENIO
from cl_conveniomaterialvalores as A, cl_convenios as C
outer apply (select
b.*
from cl_materiais as b
where b.handle = a.material) mat
outer apply (select
c.*
from cl_convenio as c
where c.handle = a.convenio) cv
where A.data < '01.08.2018 00:00'
group by mat.nome, a.valor, cv.nome
order by max(a.data) desc
normalmente não utilizo referenciar tabelas assim "from cl_conveniomaterialvalores as A, cl_materiais as B, cl_convenios as C", nos meus scripts tenho a impressão que é performático, vc pode substituir por left join por exemplo, ou o outer apply, algumas vezes o outer apply eh mais performático que o left join, mas ai tem que testar e ver o que melhor se encaixa com o seu script.
espero ter ajudado.
Atenciosamente,
Gostei + 0
28/08/2018
Diego
Então: Basicamente que quero é listar a maior data de atualização de valor do produto (abaixo do dia 01;08), trazendo essa data, esse produto, o valor, e qual convênio ele pertence.
O outer apply não é suportado pelo Firebird.... Então substitui pelo LEFT JOIN, ficando assim
select
max(A.data) as ULTIMAATUALIZACAO,
mat.nome,
A.valor,
cv.nome as CONVENIO
from cl_conveniomaterialvalores as A, cl_convenios as C
left JOIN (select
b.*
from cl_materiais as b
where b.handle = a.material) mat
left JOIN (select
c.*
from cl_convenio as c
where c.handle = a.convenio) cv
where A.data < '01.08.2018 00:00'
group by mat.nome, a.valor, cv.nome
order by max(a.data) desc
Porém está dando erro no where após atribuir aquele left join como cv
SQL error code = -104.
Token unknown - line 15, column 1.
where.
Gostei + 0
28/08/2018
Diego
Muito obrigado pelo retorno e atenção. A performance não seria preocupação nesse momento, uma vez que eu devo gerar esse relatório uma única vez. Vou tentando aqui baseado no que você sugeriu. De qualquer forma, se conseguir montar um código ficaria ainda melhor hehe. Abraços
Gostei + 0
28/08/2018
Alex Lekao
Basicamente para vc ter uma ideia mesmo.
select
mat.nome,
(select
first 1 a.data
from cl_conveniomaterialvalores as a
where a.convenio = mat.handle
orde by a.data desc) as ultdata,
(select
from cl_convenio as cv
where cv.convenio = mat.handle
order by cv.data desc) as maxpreco
from cl_materiais as mat
group by mat.nome, a.valor, cv.nome
Atenciosamente,
Gostei + 0
28/08/2018
Diego
No segundo Select, que campo você quis ler? Está assim:
(select
from cl_convenio as cv
Seria o nome?
Gostei + 0
28/08/2018
Alex Lekao
era preco.
esqueci de colocar, eh que eu monto a estrutura do from primeiro, depois eu relaciono os campos, que o SGDB indica os campos da tabela, fica mais facil, nao preciso lembrar os campo da tabela. rsrsr
Gostei + 1
28/08/2018
Emerson Nascimento
select
mat.nome,
cmv.valor,
cmv.data as ULTIMAATUALIZACAO,
cv.nome as CONVENIO
from
cl_materiais as mat
left join
(select material, max(data) as ultdata
from cl_conveniomaterialvalores
where data < '01-08-2018'
group by material) ult on ult.material = mat.handle
left join
cl_conveniomaterialvalores as cmv on cmv.material = mat.handle
and cmv.data = ult.data
left join
cl_convenio as cv on cv.handle = cmv.convenioou assim:
select
mat.nome,
cmv.valor,
cmv.data as ULTIMAATUALIZACAO,
cv.nome as CONVENIO
from
cl_materiais as mat
left join
(select material, convenio, max(data) as ultdata
from cl_conveniomaterialvalores
where data < '01-08-2018'
group by material, convenio) ult on ult.material = mat.handle
left join
cl_conveniomaterialvalores as cmv on cmv.material = mat.handle
and cmv.convenio = ult.convenio
and cmv.data = ult.data
left join
cl_convenio as cv on cv.handle = cmv.convenioGostei + 1
29/08/2018
Diego
Muito obrigado pela atenção... No fim das contas consegui fazer com um simples subselect, como você havia sugerido anteriormente...
SELECT a.DATA, a.valor, a.material,b.nome, c.nome as convenio
FROM CL_CONVENIOMATERIALVALORES a, cl_convenios c, cl_materiais b
WHERE a.DATA =
(SELECT max(data) FROM CL_CONVENIOMATERIALVALORES WHERE material=a.material) AND a.convenio=c.handle AND a.material=b.handle AND a.DATA < '01.08.2018 00:00' Bastou fazer o subselect no where para conseguir os resultados...
Obrigado e abraços....
Gostei + 1
29/08/2018
Alex Lekao
Que bom que deu certo e pude ajudar.
Qqr coisa, estamos ai.
Eu soubendo de algo, compartilho.
Atenciosamente,
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)