递归CTE以识别数据中的循环引用

时间:2018-11-29 16:12:51

标签: sql-server common-table-expression recursive-cte

我正在尝试在我的数据中识别需要递归cte的递归/循环引用。

例如,我有一个包含Product_IDInner_Product_ID的表。当Product_ID A位于Product_ID B内部,Product_ID C位于Product_ID A内部时,我想要结果。

样本数据

PRODUCT_ID    INNER_PRODUCT_ID
   12              36
   24              12
   36              24
   1               2
   3               4

预期产量

PRODUCT_ID    INNER_PRODUCT_ID
   12              36
   24              12
   36              24

我尝试使用cte进行基本查询,但不确定如何针对此问题实施递归cte:

;WITH RNCTE
AS (   SELECT *,
           ROW_NUMBER() OVER (PARTITION BY pr1.PRODUCT_ID
                              ORDER BY pr1.PRODUCT_ID
                             ) rn
       FROM
           TableName pr1),
      cte
AS (   SELECT *
       FROM RNCTE
       WHERE RNCTE.rn = 1
       UNION ALL
       SELECT *
       FROM cte   c
           JOIN RNCTE r
                   ON r.PRODUCT_ID = c.PRODUCT_ID
                      AND r.rn = c.rn + 1)
SELECT *
FROM  cte;

2 个答案:

答案 0 :(得分:1)

尝试此操作-它遍历链接的记录,并查找“ walk”是否最终终止。如果持续时间超过表中的记录数,则它必须是循环。 “高效”我不确定!

;WITH UCNT AS (SELECT count(0) c from products),
        RNCTE 
    AS (SELECT 1 as Levle, Product_ID, INNER_PRODUCT_ID FROM Products
        UNION ALL
        SELECT levle + 1, P.Product_ID, P.INNER_PRODUCT_ID
                     FROM RNCTE R 
                        JOIN Products P 
                            ON P.PRODUCT_ID = R.INNER_PRODUCT_ID
        WHERE levle <= (SELECT c + 2 FROM UCNT))
        --when the recursion count levle exceeds the count of records in the table, 
        --we must have recursion, because 
        --termination has to otherwise occur.  The most extreme case is 
        --that all records are linked, with termination
        --after this, we have to be in a 'loop' 
        SELECT TOP 1 with ties * FROM RNCTE order by levle desc
        option (maxrecursion 0)

答案 1 :(得分:0)

我认为您不需要使用CTE RECUSRIVE CTE

SELECT pr1.*
FROM TableName pr1
WHERE EXISTS (SELECT 1 FROM TableName pr2 WHERE pr2.INNER_PRODUCT_ID = pr1.PRODUCT_ID);