Select trazendo somente registros da última data
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
Post 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
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...
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,
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.
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
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,
28/08/2018
Diego
No segundo Select, que campo você quis ler? Está assim:
(select
from cl_convenio as cv
Seria o nome?
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
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.convenio
ou 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.convenio
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....
29/08/2018
Alex Lekao
Que bom que deu certo e pude ajudar.
Qqr coisa, estamos ai.
Eu soubendo de algo, compartilho.
Atenciosamente,
Clique aqui para fazer login e interagir na Comunidade :)