Фильтрация дубликатов из запроса по полю с приоритезацией
Нужно реализовать фильтрацию дубликатов в списке по списку приоритетов
Есть класс, составляющий список List<Trade>
public class Trade { int id, int sectionId, String name, ... }
И есть приоритет секций (sectionId) - List<Integer> priorities = List.of(63, 174, 74, 36, 37, 61, ...)
Возможна ситуация, когда из репозитория вытянутся строки с одинаковым id (2, 3 или больше штук), но с разным sectionId и нужно сделать фильтрацию списка List<Trade> согласно priorities, чтобы в исходном списке (или в новом) остались только строки с уникальными id
Пример исходных данных:
id, section_id, name
118,36,МБ
163,36,МБ
163,66,ОТС
226,36,МБ
В наборе две строки с id = 163:
163,36,МБ
163,66,ОТС
должна быть одна, согласно priorities в приоритете sectionId = 63, в этих двух строках такого sectionId нет, идем по списку дальше пока не попадем на sectionId = 36, соответственно берем строку 1:
163,36,МБ
Итоговый результат должен выглядеть так:
id, section_id, name
118,36,МБ
163,36,МБ
226,36,МБ
Добавлю, что для вытягивания записей Trade используется JpaRepository и в качестве БД - MS SQL с native query в репозитории, поэтому если есть способ сделать фильтрацию прямо в запросе, наверное так будет даже лучше
Мое решение на данный момент -
- вытянуть все записи
Stream<Trade> findAll() - сгруппировать в мапу по id
collect(Collectors.groupingBy(Trade::getId)); - создать список через
stream().flatMap(Collection::stream), чтобы было откуда удалять - отфильтровать values() по size() > 1
- в каждом таком списке реализовать
sort()с компаратором поpriorities - удалить все элементы, кроме первого в исходном списке
В принципе вариант рабочий, но тяжеловесный и как считаю не очень проходит для 2-3к строк
Ответы (1 шт):
Приведу пример, как понял я (использую postgres, но, думаю, разницы большой не будет).
create table public.trade
(
id integer not null,
section_id integer not null,
name varchar(255) not null
);
create table trade_priority
(
id integer not null,
priority integer
);
Запрос:
select t.*
from trade t
inner join trade_priority tp on tp.id = t.section_id
and (t.id, tp.priority) in
(select tr.id, max(tp.priority)
from trade tr
inner join trade_priority tp on tp.id = tr.section_id
group by tr.id)