如何创建查询以跟踪给定记录的连接?

时间:2014-07-22 17:45:25

标签: sql sqlplus

我有一个表示地图的连接节点表,这些节点有各自的from和to节,指定它们的连接方式:

  < - >从 - NODENUMBER1 - 到 - 从 - NODENUMBER2 - 到

我正在运行一些测试试图从这个地图中删除部分,我想选择一个节点来删除它下游的所有节点。

我想知道如何通过SQL查询来实现这一点,例如这个伪SQL:

select A.nodes from node_table A, node_table B
where A.to_section = B.from_section
and **A.starting_node = NODENUMBER_X**;

因此,通过设置NODENUMBER_X,查询将生成连接到NODENUMBER_X下游的所有节点。

1 个答案:

答案 0 :(得分:0)

递归并不总是很有效率,但它是解决此类问题的一种方法。假设node_table具有唯一字段node_id(int):

declare @start_node_id int, @loop_limit int, @loop_count int;

set @start_node_id = 1234;  -- Insert the node ID you want to start from.
set @loop_limit = 1000;     -- Set a limit on the number of loop iterations.
set @loop_count = 0;

create table #NODES_TO_DELETE(NODE_ID int);

-- Get first child nodes, directly linked to start node.
insert into #NODES_TO_DELETE(NODE_ID)
select A.NODE_ID
from node_table A inner join node_table B on B.from_section = A.to_section
where B.NODE_ID = @start_node_id;

-- If there are child nodes not yet in our temp table, continue loop.
WHILE EXISTS(select 1
    from node_table A inner join node_table B on B.from_section = A.to_section
    inner join #NODES_TO_DELETE D on B.NODE_ID = D.NODE_ID
    left join #NODES_TO_DELETE X on A.NODE_ID = X.NODE_ID
    where X.NODE_ID is null) and 
@loop_count < @loop_limit
BEGIN
    -- Add child nodes to temp table. Avoid duplicate IDs.
    insert into #NODES_TO_DELETE(NODE_ID)
    select distinct A.NODE_ID
    from node_table A inner join node_table B on B.from_section = A.to_section
    inner join #NODES_TO_DELETE D on B.NODE_ID = D.NODE_ID
    left join #NODES_TO_DELETE X on A.NODE_ID = X.NODE_ID
    where X.NODE_ID is null;

    -- Increment loop count.
    set @loop_count = @loop_count + 1;
END

IF @loop_count > @loop_limit
    print 'Loop limit exceeded.';   -- We've exceeded our loop limit. May not have all matches.
ELSE
    delete N    -- Delete all nodes inserted into our temp table.
    from node_table N
    inner join #NODES_TO_DELETE D on N.NODE_ID = D.NODE_ID;

drop table #NODES_TO_DELETE;