none
不用存储过程,使用with递归查询邻接表时,如何在查询过程中防止重复递归查询已经查询过的节点? RRS feed

  • 问题

  • 比如,1节点属于2节点和3节点两个节点的子节点或者子孙节点,1节点内部也可能会有子节点和子孙节点。

    当我对2节点和3节点进行递归的in查询或者对包含2节点和3节点的父节点或祖先节点进行递归查询时。对2节点查询获得了1节点以及1节点内部的子节点,子孙节点,那么再对3节点查询时得到1节点过滤掉,不在往1节点下面进行递归查询,

    类似的这种情况下,或者说有共同子节点或子孙节点的邻接表,如何在递归查询过程中防止重复递归查询,而不是查询完后去重复?这种查询语法不知道格式怎么写


    WITH cte AS (

    SELECT NodeId FROM NodeRelation WHERE NodeId in(?,?,?……) UNION ALL SELECT p.NodeId FROM NodeRelation p INNER JOIN cte t ON p.directionNodeId = t.NodeId )

    有事忘记补充了,补充内容

    Create table Node( nodeId int primary key, nodeName nvarchar(100) ) Create table NodeRelation ( NrId int identity(1,1) primary key , NodeId int references Node(nodeId ), directionNodeId int unique(nodeId ,nodeId ) ) ////这种数据结构 ,node代表节点信息,nodeRelation,代表节点之间的关联。

    NodeId代表被指向的节点 directionNodeId代表指向NodeId的节点,directionNodeId有0或null的值情况下,代表没有

    节点指向NodeId或者说是顶点 当然我的程序操作流程不会出现无限层次的关联。不会出现诸如3→2→1→3或2→3→1→3这种类似

    环状闭合的情况

    图:

    下是例表说明,如果我用上面的sql查询2和3这两个节点,结果集的nodeId列会出现2个值为1的行,如果节点1有内部节点,还会列出两个1节点内部所有的节点,所以我的意思是,如果一个节点id在查询时被列出来了,那么以后对其他节点的查询过程,碰到已经得到的节点id就忽略掉不对该节点进行递归。如果上面的例子某部分放大一点,1节点内部有1000个子节点或子孙节点,那么对2节点和3节点的查询。结果集不是大约1000个,而会有2000个左右



    NrId nodeId directionNodeId 
    1 1 0
    2 2 0
    3 3 0
    4 9 3
    5 1 9
    6 8 2
    7 1 2
    8 4 1
    9 5 1
    10 6 1


















    • 已编辑 Trian555 2018年11月23日 7:01
    2018年11月22日 5:44

全部回复

  • Hi Trian555,

    您可以分享一下您的原始表的结构吗?是类似于下面的这种吗?另外,为什么要“查询过程中防止重复递归查询已经查询过的节点?”?是防止额外的硬件开销还是防止结果集中有重复数据,如果是防止重复数据,可以用distinct。

    Best Regards,

    Teige


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年11月22日 8:37
    版主
  • 你描述的这个结构本来就不是树,那么,就要看你想把这个结构表示为树,还是作为一个有向图来处理了。

    但是,从你给出的代码来说,每条记录有一个ParentId,其实不会出现你描述的情况的,每个节点有且只有一个Parent(按照通常情况来说,id是表的primary key)


    想不想时已是想,不如不想都不想。

    2018年11月22日 9:05
    版主
  • with cte 
    as
    (
    select id from (select *, ROW_NUMBER()Over(PARTITION by id Order by id) qq from dbo.tree_path) as mm  where path in (1,4) and qq = 1
    union all
    select  a.id from dbo.tree_path as a
    inner join (select id from (select id ,ROW_NUMBER()Over(PARTITION by id Order by id) Rn from cte) as s where Rn = 1 ) as b
    on b.id=a.path
    )
    select * from cte


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年11月22日 9:08
    版主
  • Hi Trian555,

    您可以分享一下您的原始表的结构吗?是类似于下面的这种吗?另外,为什么要“查询过程中防止重复递归查询已经查询过的节点?”?是防止额外的硬件开销还是防止结果集中有重复数据,如果是防止重复数据,可以用distinct。

    Best Regards,

    Teige


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    已补充
    2018年11月23日 1:59
  • 你描述的这个结构本来就不是树,那么,就要看你想把这个结构表示为树,还是作为一个有向图来处理了。

    但是,从你给出的代码来说,每条记录有一个ParentId,其实不会出现你描述的情况的,每个节点有且只有一个Parent(按照通常情况来说,id是表的primary key)


    想不想时已是想,不如不想都不想。


    已补充
    2018年11月23日 1:59
  • 如果你希望一个Node只出现一次,Teige Gao 的代码可以满足你的需求

    想不想时已是想,不如不想都不想。

    2018年11月23日 4:17
    版主