Tenho uma tabela assim:
ID | Val | Kind
----------------------
1 | 1337 | 2
2 | 1337 | 1
3 | 3 | 4
4 | 3 | 4
Eu quero fazer um SELECT
que retornará apenas a primeira linha para cada um Val
, ordenando por Kind
.
Saída de amostra:
ID | Val | Kind
----------------------
2 | 1337 | 1
3 | 3 | 4
Como posso construir esta consulta?
Use uma expressão de tabela comum (CTE) e uma função de janela/classificação/particionamento como ROW_NUMBER .
Esta consulta criará uma tabela na memória chamada ORDERED e adicionará uma coluna adicional de rn que é uma sequência de números de 1 a N. A PARTITION BY indica que deve reiniciar em 1 toda vez que o valor de Val mudar e quisermos ordenar linhas pelo menor valor de Kind.
A abordagem acima deve funcionar com qualquer RDBMS que tenha implementado a função ROW_NUMBER(). O Oracle possui algumas funcionalidades elegantes, conforme expresso na resposta de mik, que geralmente produzirá um desempenho melhor do que esta resposta.
Esta solução também usa
keep
, masval
tambémkind
pode ser calculada de forma simples para cada grupo sem uma subconsulta:dbfiddle aqui
KEEP…FIRST e KEEP…LAST são um recurso de agregações específico do Oracle — você pode ler sobre isso aqui nos documentos do Oracle ou em ORACLE_BASE :
A solução do bilinkc funciona bem, mas pensei em jogar fora a minha também. Tem o mesmo custo, mas pode ser mais rápido (ou mais lento, não testei). A diferença é que ele usa o First_Value em vez de Row_Number. Como estamos interessados apenas no primeiro valor, na minha opinião é mais direto.
Dados de teste.
Se preferir, aqui está o equivalente CTE.
Você pode usar
keep
para selecionar umid
de cada grupo:dbfiddle aqui
selecione * de (selecione t1.*,ROW_NUMBER() OVER (PARTITION BY Val ORDER BY Val desc) como seqnum de tablename t1) onde seqnum=1;