У меня есть такая таблица:
ID | Val | Kind
----------------------
1 | 1337 | 2
2 | 1337 | 1
3 | 3 | 4
4 | 3 | 4
Я хочу сделать, SELECT
что будет возвращать только первый ряд для каждого Val
, упорядочив по Kind
.
Образец вывода:
ID | Val | Kind
----------------------
2 | 1337 | 1
3 | 3 | 4
Как я могу построить этот запрос?
oracle
greatest-n-per-group
BrunoLM
источник
источник
ORDER BY ID DESC
, но это не имеет отношения к вопросу. В этом примере мне все равно.Ответы:
Это решение также использует
keep
, ноval
иkind
может также быть просто для каждой группы без подзапроса:dbfiddle здесь
KEEP… FIRST и KEEP… LAST - это особенность Oracle для агрегатов, о которой вы можете прочитать здесь, в документации Oracle или на ORACLE_BASE :
источник
Используйте общее табличное выражение (CTE) и функцию управления окнами / ранжирования / разбиения, например ROW_NUMBER .
Этот запрос создаст таблицу в памяти с именем ORDERED и добавит дополнительный столбец rn, представляющий собой последовательность чисел от 1 до N. Параметр PARTITION BY указывает, что он должен перезапускаться с 1 каждый раз, когда изменяется значение Val, и мы хотим упорядочить строки по наименьшему значению вида.
Приведенный выше подход должен работать с любой СУБД, в которой реализована функция ROW_NUMBER (). Oracle обладает элегантной функциональностью, выраженной в ответе Мика, которая обычно дает более высокую производительность, чем этот ответ.
источник
Решение bilinkc работает отлично, но я решил, что тоже выброшу. Он имеет такую же стоимость, но может быть быстрее (или медленнее, я его не тестировал). Разница в том, что он использует First_Value вместо Row_Number. Поскольку нас интересует только первое значение, на мой взгляд, оно более простое.
Тестовые данные.
Если вы предпочитаете, вот эквивалент CTE.
источник
id
не уникальны.Вы можете использовать
keep
для выбораid
из каждой группы:dbfiddle здесь
источник
источник