snowflake-cloud-data-platformsnowflake-task

Does snowflake has function LISTAGG(column_name [, delimiter] ON OVERFLOW TRUNCATE )?


It seems "ON OVERFLOW TRUNCATE" feature is not available in snowflake which goes with LISTAGG in Oracle. Is there a alternate function or workaround to it?


Solution

  • 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
    );
    

    gives the values with total (prior to delimiters)

    ,sum(length(str)+2)over(order by id) as s_str
    

    allows you to take the size of the delimiter ', ' into account

    or if you want some truncating suffix like '...' then this will do that..

    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
    );
    

    giving

    LISTAGG
    'abcdef, dfgsdfh, ...'
    

    to rewrite as CTEs which does not change anything...

    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;