Bara med lite ansträngning. Något så här:
select listagg((case when running_len < 4000 then oi.impression end), ',') within group (order by oi.line)
from (select oi.*,
sum(length(oi.impression) + 1) over (partition by ?? order by oi.line) as running_len
from order_impression oi
) oi
group by ??;
Detta beräknar löplängden och aggregerar endast värden som inte överstiger längden. ??
är vad du än använder för aggregering. Detta förutsätter att line
är unik, så order by
är stabil.
Detta inkluderar inte impression
som överstiger längden -- och ingenting efter det. Det skär inte av intrycket. Den logiken är möjlig, men den komplicerar frågan.