Another way to do it using Arrays (this is a more general solution which 
does not need values to be converted to string/varchar (better for numeric 
values)):

with recursive
    data (old_value, new_value) as (
        select 'foo', 'bar' union
        select 'bar', 'baz' union
        select 'baz', 'foo' union
        select 'qux', 'bar'
    ),
    related (the_value, all_values) as (
        select 'qux', array ['qux']
        union
        select
            case the_value when old_value then new_value else old_value end,
            array_append(all_values, case the_value when old_value then 
new_value else old_value end)
        from related join data on the_value in (old_value, new_value)
        where not array_contains(all_values, case the_value when old_value 
then new_value else old_value end)
    )
select distinct the_value from related;

I would be interested in hearing about other people's techniques.
On Tuesday, 14 October 2025 at 11:13:34 UTC+2 Xavier Dury wrote:

> Hello,
>
> I know recursive CTEs are somewhat experimental in H2 but is there an ETA 
> to support the stopping of the recursion when it starts producing records 
> that have been previously produced?
>
> In the meantime, I'm using a counter like this as a stop condition (but 
> the problem is that it will only stop when the counter reaches 0 which 
> makes it do useless rounds):
>
> with recursive
>     data (old_value, new_value) as (
>         select 'foo', 'bar' union
>         select 'bar', 'baz' union
>         select 'baz', 'foo' union
>         select 'qux', 'bar'
>     ),
>     related (the_value, max_recursion) as (
>         select 'qux', 10
>         union
>         select
> case the_value when old_value then new_value else old_value end,
> max_recursion - 1
>         from related join data on the_value in (old_value, new_value)
>         where max_recursion > 0
>     )
> select distinct the_value from related;
>
> I could also do something like this which could stop earlier (but I don't 
> know if there's a performance hit with string operations or a memory 
> limitation compared to the previous option):
>
> with recursive
>     data (old_value, new_value) as (
>         select 'foo', 'bar' union
>         select 'bar', 'baz' union
>         select 'baz', 'foo' union
>         select 'qux', 'bar'
>     ),
>     related (the_value, all_values) as (
>         select 'qux', '|qux|'
>         union
>         select
>             case the_value when old_value then new_value else old_value 
> end,
>             all_values || case the_value when old_value then new_value 
> else old_value end || '|'
>         from related join data on the_value in (old_value, new_value)
>         where locate('|' || case the_value when old_value then new_value 
> else old_value end || '|', all_values) = 0
>     )
> select distinct the_value from related;
>
> Is there a better way to stop recursion until CTEs support is improved on 
> this point?
>
> Thanks,
> KR,
> Xavier

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/h2-database/26185ea2-c2ea-4765-b947-5469e62dfab2n%40googlegroups.com.

Reply via email to