Это должно быть семантически эквивалентно набору, оставленному в таблице temp после удаления в существующем коде. Хотя я бы согласился с AR, что таблица User не нужна, если она не содержит меньше user_id, чем user_role. В противном случае это никак не ограничивает набор. Если пользователь содержит больше user_id, чем user_role, это не изменит результирующий набор. User_role является основным драйвером в этом запросе с небольшим ограничением из таблицы cmp_role.
select a.user_id,
a.role_id,
a.participant_code,
a.status_id
from (select a.user_id,
a.role_id,
a.participant_code,
max(status_id) status_id
from user_role a,
(select role_id
from cmp_role
where group_id = 3
) b
where a.participant_code is not null
and a.active in (0, 1, 3)
and sysdate between a.effective_from_date and a.effective_to_date
and a.role_id = b.role_id
group by a.user_id,
a.role_id,
a.participant_code
) a
user c
where a.user_id = c.user_id;
Если производительность все еще остается низкой, то, возможно, следовало бы посмотреть на индексы некоторых полей, используемых для ограничения данных (user_role.role_id, user_role.participant_code, user_role.active, user_role.effective_from_date, user_role.effective_to_date).
Конечно, для объяснения того, что делает Oracle при выполнении этого запроса на основе ваших данных и структуры, потребуется план или трассировка объяснения.