Фильтрация дубликатов из запроса по полю с приоритезацией

Рейтинг: -1Ответов: 1Опубликовано: 28.03.2023

Нужно реализовать фильтрацию дубликатов в списке по списку приоритетов

Есть класс, составляющий список 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 в репозитории, поэтому если есть способ сделать фильтрацию прямо в запросе, наверное так будет даже лучше

Мое решение на данный момент -

  1. вытянуть все записи Stream<Trade> findAll()
  2. сгруппировать в мапу по id collect(Collectors.groupingBy(Trade::getId));
  3. создать список через stream().flatMap(Collection::stream), чтобы было откуда удалять
  4. отфильтровать values() по size() > 1
  5. в каждом таком списке реализовать sort() с компаратором по priorities
  6. удалить все элементы, кроме первого в исходном списке

В принципе вариант рабочий, но тяжеловесный и как считаю не очень проходит для 2-3к строк

Ответы

▲ 0

Приведу пример, как понял я (использую 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)