select listagg(str, ', ') within group (order by id) as listagg
from (
select id
,str
,sum(length(str))over(order by id) as s_str
from (
select * from values(1,'abcdef'),(2,'dfgsdfh'),(3,'jgeg'),(4,'ergegr') s(id,str)
)
qualify s_str <= 20
);
дает значения с итогом (до разделителей)
,sum(length(str)+2)over(order by id) as s_str
позволяет вам принять размер разделителя ',' во внимание
или, если вы хотите, чтобы некоторые усечение суффикса, например '...'
, тогда это будет сделано ..
select listagg(str, ', ') within group (order by id) as listagg
from (
select id
,s_str <= 20 as underlimit
,iff(underlimit, str, '...') as str
from (
select id
,str
,sum(length(str)+2)over(order by id) as s_str
from (
select * from values(1,'abcdef'),(2,'dfgsdfh'),(3,'jgeg'),(4,'ergegr') s(id,str)
)
)
qualify underlimit or row_number() over (partition by underlimit order by id) = 1
);
, давая
LISTAGG
'abcdef, dfgsdfh, ...'
для переписывания в виде CTE, которые ничего не изменят ...
with data as (
select id
,str
,sum(length(str)+2)over(order by id) as s_str
from values
(1,'abcdef'),
(2,'dfgsdfh'),
(3,'jgeg'),
(4,'ergegr')
s(id,str)
), check_length_and_limit as (
select id
,s_str <= 20 as underlimit
,iff(underlimit, str, '...') as str
from data
qualify underlimit or row_number() over (partition by underlimit order by id) = 1
)
select listagg(str, ', ') within group (order by id) as listagg
from check_length_and_limit;