Solo con un po' di fatica. Qualcosa del genere:
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 ??;
Questo calcola la lunghezza corrente e aggrega solo i valori che non superano la lunghezza. Il ??
è tutto ciò che stai usando per l'aggregazione. Questo presuppone che line
è unico, quindi order by
è stabile.
Questo non includerà l'impression
che supera la lunghezza - e niente dopo. Non taglia l'impressione. Questa logica è possibile, ma complica la query.