Рекурсивный метод определения циклической ссылки в данных - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь определить рекурсивную / циклическую ссылку в моих данных, для которых мне нужен рекурсивный cte.

Например, у меня есть таблица, которая содержит Product_ID и Inner_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 голосов
/ 29 ноября 2018

попробуйте это - он просматривает связанные записи и находит, завершается ли 'прогулка' или нет.Если это длится больше, чем количество записей в таблице, то это должен быть цикл.«Эффективный» Я не уверен в этом!

;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)
0 голосов
/ 29 ноября 2018

Я думаю, вам не нужно использовать CTE или RECUSRIVE CTE:

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