Alleen met een beetje moeite. Zoiets als dit:
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 ??;
Dit berekent de looplengte en aggregeert alleen waarden die de lengte niet overschrijden. De ??
is wat u gebruikt voor aggregatie. Dit veronderstelt wel dat line
is uniek, dus de order by
is stabiel.
Dit omvat niet de impression
dat de lengte overschrijdt -- en daarna niets meer. Het snijdt de indruk niet weg. Die logica is mogelijk, maar het bemoeilijkt de zoekopdracht.