Mam taki stół:
ID | Val | Kind
----------------------
1 | 1337 | 2
2 | 1337 | 1
3 | 3 | 4
4 | 3 | 4
Chcę zrobić SELECT
, który zwróci tylko pierwszy wiersz dla każdego Val
, uporządkuj według Kind
.
Przykładowe dane wyjściowe:
ID | Val | Kind
----------------------
2 | 1337 | 1
3 | 3 | 4
Jak zbudować to zapytanie?
oracle
greatest-n-per-group
BrunoLM
źródło
źródło
ORDER BY ID DESC
, ale to nie ma znaczenia dla pytania. W tym przykładzie mnie to nie obchodzi.Odpowiedzi:
To rozwiązanie wykorzystuje również
keep
, aleval
ikind
może być w prosty sposób obliczony dla każdej grupy bez podkwerendzie:dbfiddle tutaj
KEEP… FIRST i KEEP… LAST są specyficzną dla Oracle funkcją agregatów - o której możesz przeczytać tutaj w dokumentach Oracle lub na ORACLE_BASE :
źródło
Użyj wspólnego wyrażenia tabelowego (CTE) i funkcji okienkowania / rankingu / partycjonowania, takich jak ROW_NUMBER .
Ta kwerenda utworzy tabelę w pamięci o nazwie ORDERED i doda dodatkową kolumnę rn, która jest sekwencją liczb od 1 do N. PARTITION BY wskazuje, że powinna ona restartować się o 1 za każdym razem, gdy zmienia się wartość Val i chcemy zamówić wiersze według najmniejszej wartości rodzaju.
Powyższe podejście powinno działać z każdym RDBMS, który zaimplementował funkcję ROW_NUMBER (). Oracle ma pewną elegancką funkcjonalność, wyrażoną w odpowiedzi mik, która ogólnie przyniesie lepszą wydajność niż ta odpowiedź.
źródło
rozwiązanie bilinkca działa dobrze, ale pomyślałem, że też go wyrzucę. Ma taki sam koszt, ale może być szybszy (lub wolniejszy, nie testowałem go). Różnica polega na tym, że używa First_Value zamiast Row_Number. Ponieważ interesuje nas tylko pierwsza wartość, moim zdaniem jest to prostsze.
Dane testowe.
Jeśli wolisz, oto odpowiednik CTE.
źródło
id
są unikalne.Możesz użyć,
keep
aby wybraćid
z każdej grupy:dbfiddle tutaj
źródło
źródło