Usuário com melhor resposta
Por favor, como posso montar esta query?

Pergunta
-
Caros amigos,
Eu tenho uma tabela com mais ou menos a seguinte estrutura:
id_localidade id_produto custo
1 2 1.3
1 2 1.6
1 2 1.5
2 4 2.1
2 4 2.3
2 4 2.2
Eu gostaria de fazer uma SELECT que me retornasse os seguintes registros:
id_localidade id_produto custo
1 2 1.5
2 4 2.2
Ou seja, o último valor (na ordem de inserção na tabela) para cada combinação de localidade e produto.
Eu estou tentando:
SELECT id_localidade, id_produto, ??? FROM tabela GROUP BY id_localidade, id_produto, com isso eu agrupo os campos id_localidade e id_produto, mas não conheço nenhuma função que retorna o último custo encontrado.
Eu até consegui fazer com uma subquery nesse ???, mas ela fica muito, muito lenta.
Alguém sabe me dizer como posso montar essa query?
Obrigado.
[]'s!
Respostas
-
Olá Jônatas,
Nesse caso é possível, pois, através do ID, podemos afirmar que o "último" é o que tem o maior ID sem depender da ordem física dos registros (que não temos nenhum controle). Veja o exemplo:
Code Snippetdeclare
@t table (id int, id_localidade int, id_produto int, custo decimal(2,1))insert
into @t values (1,1,2,1.3)insert
into @t values (2,1,2,1.6)insert
into @t values (3,1,2,1.5)insert
into @t values (4,2,4,2.1)insert
into @t values (5,2,4,2.3)insert
into @t values (6,2,4,2.2)select
t.*from
@t as tinner
join (select
from
@t group by id_localidade, id_produto) as uon
t
.id_produto = u.id_produto andt
.id = u.ultimo_idorder
by t.id[ ]s,
Gustavo
-
Olá Jônatas,
Visto que essa dúvida está muito recorrente, montei uma explicação detalhada no meu blog.
Como retornar o último registro por grupo ?
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!277.entry
[ ]s,
Gustavo Maia Aguiar
Todas as Respostas
-
Olá Jônatas Guimarães,
Da forma como está exposto, sua consulta não é possível de ser realizada.
Um banco de dados recupera seus dados com base em conjuntos e pode realizar seus filtros com base em determinados critérios. O conjunto {1, 2, 3} é semelhante ao conjunto {2, 1, 3} pois ambos possuem os mesmos membros. Uma vez que a ordem de um conjunto não importe e que não haja nenhum critério para estipular o último custo não é possível retornar a posição desejada.
Só poderemos elaborar a consulta se houver algum critério que diga que o custo 1.5 é o último para a combinação id_localidade 1 e id_produto 2. Não podemos confiar na ordem de inserção física. Se esse critério não existir, não será possível recuperar essa informação de forma confiável.
Normalmente há um identificador seqüencial ou uma coluna de data. Nenhuma dessas está presente ?
[ ]s,
Gustavo
http://gustavomaiaaguiar.spaces.live.com
-
É SQL Server 2005?
Caso seja positivo, tente adaptar o código que escrevi abaixo.Caso você não tenha uma coluna indicando qual é o ultimo registro inserido, pode criar uma usando o ROW_Number...
declare
@Tab table(id_localidade Int, id_produto Int, custo Float)insert
into @Tab(id_localidade, id_produto, custo)values
(1,2,1.3)insert
into @Tab(id_localidade, id_produto, custo)values
(1,2,1.6)insert
into @Tab(id_localidade, id_produto, custo)values
(1,2,1.5)insert
into @Tab(id_localidade, id_produto, custo)values
(2,4,2.1)insert
into @Tab(id_localidade, id_produto, custo)values
(2,4,2.3)insert
into @Tab(id_localidade, id_produto, custo)values
(2,4,2.2)declare
@Tab_2 table(ROW Int, id_localidade Int, id_produto Int, custo Float)insert
into @Tab_2select
ROW_NUMBER() OVER(PARTITION BY id_localidade ORDER BY id_produto DESC) ROW, *from
@Tabselect
a.* from @Tab_2 ainner
join (select MAX(row) row, id_localidade, id_produto from @Tab_2 group by id_localidade, id_produto) as b on a.id_localidade = b.id_localidade and a.id_produto = b.id_produto and a.Row = b.Roworder
by ID_Localidade, ID_ProdutoSabe que achei que ficou bem confuso? rs... bom.. já serve para dar o caminho das pedras.. se tiver alguma dúvida é só falar..
-
Agradeço desde já a ajuda Gustavo.
Posso colocar um identificador sim, ficaria algo assim:
id id_localidade id_produto custo
1 1 2 1.3
2 1 2 1.6
3 1 2 1.5
4 2 4 2.1
5 2 4 2.3
6 2 4 2.2
Não sei se é exatamente isto que você está falando, mas se for, mesmo desta forma, como eu consigo obter o que eu preciso?
Grato.
[]'s
Jônatas -
Olá Jônatas,
Nesse caso é possível, pois, através do ID, podemos afirmar que o "último" é o que tem o maior ID sem depender da ordem física dos registros (que não temos nenhum controle). Veja o exemplo:
Code Snippetdeclare
@t table (id int, id_localidade int, id_produto int, custo decimal(2,1))insert
into @t values (1,1,2,1.3)insert
into @t values (2,1,2,1.6)insert
into @t values (3,1,2,1.5)insert
into @t values (4,2,4,2.1)insert
into @t values (5,2,4,2.3)insert
into @t values (6,2,4,2.2)select
t.*from
@t as tinner
join (select
from
@t group by id_localidade, id_produto) as uon
t
.id_produto = u.id_produto andt
.id = u.ultimo_idorder
by t.id[ ]s,
Gustavo
-
Olá Jônatas,
Visto que essa dúvida está muito recorrente, montei uma explicação detalhada no meu blog.
Como retornar o último registro por grupo ?
http://gustavomaiaaguiar.spaces.live.com/blog/cns!F4F5C630410B9865!277.entry
[ ]s,
Gustavo Maia Aguiar