用警卫停止递归CTE

问题描述

我具有以下从源到目的地的分层数据,并且当出现对现有源的引用时,我想停止

create table #temp (source int,destination int);
insert into #temp values (1,3),(3,7),(7,9),(9,1);

WITH cte (Source,Destination,Level,Sources)
AS 
(
    SELECT Source,0 AS Level,CAST(Source AS VARCHAR(MAX)) + ',' AS Sources
    FROM #temp 
    WHERE [Source] = 1

    UNION ALL

    SELECT t.[Source],t.Destination,cte.[Level] + 1,cte.sources + CAST(t.source AS VARCHAR(MAX)) + ','
    FROM #temp t        
        INNER JOIN cte ON cte.Destination = t.[Source] AND (CAST(t.Destination AS VARCHAR(MAX)) + ',' NOT LIKE '%' + cte.sources + '%')
)
select * from cte

drop table #temp;

但是运行此命令时我仍然遇到最大递归错误。我应该如何正确编写保护条款?我想要的是前3个结果。

解决方法

向CTE的递归部分添加import java.util.*; class solve { static long minCost(long arr[],int n) { Queue<Long> heap = new PriorityQueue( (a,b)-> b - a ); long ans = 0; for( long i : arr ) heap.add(i); while(!heap.isEmpty()){ long f = heap.poll(); if( heap.isEmpty()) return f+ans; long s = heap.poll(); ans += f+s; heap.add(f+s); } return ans; } public static void main(String[] args) { long a[] = {4,3,2,6}; System.out.println(minCost(a,4)); } } 子句。

where

Fiddle

,

此处,在CTE的递归成员中:

INNER JOIN cte 
    ON  cte.Destination = t.[Source] 
    AND (CAST(t.Destination AS VARCHAR(MAX)) + ',' NOT LIKE '%' + cte.Sources + '%')

您错误地使用了LIKE操作数。相反:

INNER JOIN cte 
    ON cte.Destination = t.[Source] 
    AND cte.Sources NOT LIKE CONCAT('%',t.Destination,'%')

也就是说,目的地应该属于已经访问过的来源列表。请注意,使用CONCAT()会强制将数字转换为字符串,从而缩短表达式。

Demo on DB Fiddle