select string_agg(c.letter, '') as result
from (select b.letter, lag(b.letter) over (order by rownum) letter_before
from (select row_number() over () as rownum, letter
from (select unnest(string_to_array('vvvvvaassssyyyaaaaaaa', null)) as letter) as a
) as b
) as c
where c.letter_before is null or c.letter <> c.letter_before
Можно сделать функцию получения уникальной последовательности символов без повторения в SQL.
Запрос имеет следующие шаги:
a) Получение выборки строк посимвольным разбиением слова.
b) Выборка b содержит нумерацию символов rownum.
c) С помощью функции lag и колонки rownum (для выбора направления сортировки) получаем предыдущий символ слова в текущей строке.
d) Выбираем только те строки, которые содержат разные предыдущие символы и собираем символы обратно в строку result.
Усовершенствованный вариант:
select d.user_id, string_agg(d.letter, '') as result
from (select c.*, case when c.letter_before is null or c.letter_after is null or c.letter <> c.letter_before or c.letter <> c.letter_after then 1 else 0 end marker
from
(select b.user_id, b.rownum, b.letter, lag(b.letter) over (partition by b.user_id order by b.rownum) letter_before, lead(b.letter) over (partition by b.user_id order by b.rownum) letter_after
from (select a.user_id, row_number() over (partition by a.user_id) as rownum, a.letter
from (select 1 user_id, unnest(string_to_array('vasyyyaaaaaa', null)) as letter
union all
select 2 user_id, unnest(string_to_array('pettyaaaa', null)) as letter
) as a
) as b
) c
order by c.user_id, c.rownum) d
where d.marker = 1
group by d.user_id
a) Содержит 2 пользователя.
b) Добавлено слежение за передним символом lead.
с) marker дает 1 в случае "головы" или "хвоста" одинаковой последовательности символов.
d) из последовательности символов достается только голова или хвост последовательности (при наличии), что дает ограничение <3 повторений.
На всех уровнях использование оконных функций позволяет получать значения функций в пределах user_id.
PS: Данное решение демонстрирует, что можно работать в пределах стандартного синтаксиса SQL без использования хранимых процедур (с финтами ушами в виде оконных функций), но это не значит, что решение оптимально, возможно, стоит написать хранимку, с использованием классических циклов с курсорами по разбивке имени пользователя на символы.