Sql server 具有多个节点的递归CTE层次结构中每行的唯一ID

Sql server 具有多个节点的递归CTE层次结构中每行的唯一ID,sql-server,recursive-query,Sql Server,Recursive Query,我有一个表,其中包含一组构成层次结构的链接。最大的问题是,每个链接可能在不同的位置使用多次。我需要能够区分每个节点的每个实例 例如,在以下数据中,链路D-G将显示多次: ╔════════════╦════════╗ ║ SOURCE ║ TARGET ║ ╠════════════╬════════╣ ║ A ║ B ║ ║ A ║ C ║ ║ B ║ D ║ ║ B ║ E

我有一个表,其中包含一组构成层次结构的链接。最大的问题是,每个链接可能在不同的位置使用多次。我需要能够区分每个节点的每个实例

例如,在以下数据中,链路D-G将显示多次:

╔════════════╦════════╗
║     SOURCE ║ TARGET ║
╠════════════╬════════╣
║     A      ║ B      ║
║     A      ║ C      ║
║     B      ║ D      ║
║     B      ║ E      ║
║     B      ║ F      ║
║     C      ║ D      ║
║     C      ║ E      ║
║     C      ║ F      ║
║     D      ║ G      ║
║     E      ║ D      ║
║     F      ║ D      ║
╚════════════╩════════╝
我可以使用递归CTE构建层次结构,没有任何问题,但我希望为结果中的每一行提供一个唯一的ID,并将其链接到父节点的唯一ID

我最初的想法是使用row_Number+MaxID为每一行分配一个唯一的ID,直到现在,并让该行继承它的父ID,但进一步阅读和反复试验表明,这是行不通的:-

有没有人知道如何解决这个问题,或者至少给我一个线索

结果应该是这样的:

╔═════════════╦═════════════╦═══════════╦═══════════╗
║ SOURCE_DESC ║ TARGET_DESC ║ Source_ID ║ Target_ID ║
╠═════════════╬═════════════╬═══════════╬═══════════╣
║     A       ║ B           ║         0 ║         1 ║
║     A       ║ C           ║         0 ║         2 ║
║     B       ║ D           ║         1 ║         6 ║
║     B       ║ E           ║         1 ║         7 ║
║     B       ║ F           ║         1 ║         8 ║
║     C       ║ D           ║         2 ║         3 ║
║     C       ║ E           ║         2 ║         4 ║
║     C       ║ F           ║         2 ║         5 ║
║     D       ║ G           ║         3 ║        13 ║
║     E       ║ D           ║         4 ║        11 ║
║     F       ║ D           ║         5 ║        10 ║
║     D       ║ G           ║         6 ║        14 ║
║     E       ║ D           ║         7 ║        12 ║
║     F       ║ D           ║         8 ║         9 ║
║     D       ║ G           ║         9 ║        18 ║
║     D       ║ G           ║        10 ║        17 ║
║     D       ║ G           ║        11 ║        16 ║
║     D       ║ G           ║        12 ║        15 ║
╚═════════════╩═════════════╩═══════════╩═══════════╝
在这里,D-G链接显示了好几次,但在每个实例中,它都有不同的ID和不同的父ID

我已经设法做到了,但我对我的方式不满意。这似乎不是很有效,对于这个例子来说并不重要,但是对于更大的集合来说非常重要

WITH JUNK_DATA 
     AS (SELECT *, 
                ROW_NUMBER() 
                  OVER ( 
                    ORDER BY SOURCE) RN 
         FROM   LINKS), 
     RECUR 
     AS (SELECT T1.SOURCE, 
                T1.TARGET, 
                CAST('ROOT' AS VARCHAR(MAX))      NAME, 
                1                                 AS RAMA, 
                CAST(T1.RN AS VARCHAR(MAX)) + ',' AS FULL_RAMA 
         FROM   JUNK_DATA T1 
                LEFT JOIN JUNK_DATA T2 
                       ON T1.SOURCE = T2.TARGET 
         WHERE  T2.TARGET IS NULL 
         UNION ALL 
         SELECT JUNK_DATA.SOURCE, 
                JUNK_DATA.TARGET, 
                CASE 
                  WHEN RAMA = 1 THEN (SELECT [DESC] 
                                      FROM   NAMES 
                                      WHERE  ID = JUNK_DATA.SOURCE) 
                  ELSE NAME 
                END      NAME, 
                RAMA + 1 AS RAMA, 
                FULL_RAMA 
                + CAST(JUNK_DATA.RN AS VARCHAR(MAX)) + ',' 
         FROM   (SELECT * 
                 FROM   JUNK_DATA)JUNK_DATA 
                INNER JOIN (SELECT * 
                            FROM   RECUR) RECUR 
                        ON JUNK_DATA.SOURCE = RECUR.TARGET), 
     FINAL_DATA 
     AS (SELECT T2.[DESC]          SOURCE_DESC, 
                T3.[DESC]          TARGET_DESC, 
                RECUR.*, 
                ROW_NUMBER() 
                  OVER ( 
                    ORDER BY RAMA) ID 
         FROM   RECUR 
                INNER JOIN NAMES T2 
                        ON RECUR.SOURCE = T2.ID 
                INNER JOIN NAMES T3 
                        ON RECUR.TARGET = T3.ID) 
SELECT T1.SOURCE_DESC, 
       T1.TARGET_DESC, 
       ISNULL(T2.ID, 0) AS SOURCE_ID, 
       T1.ID            TARGET_ID 
FROM   FINAL_DATA T1 
       LEFT JOIN (SELECT ID, 
                         FULL_RAMA 
                  FROM   FINAL_DATA)T2 
              ON LEFT(T1.FULL_RAMA, LEN(T1.FULL_RAMA) - CHARINDEX(',', 
                 REVERSE(T1.FULL_RAMA), 2)) 
                 + ',' = T2.FULL_RAMA 
ORDER  BY SOURCE_ID, 
          TARGET_ID 

请在上查看。

从上面的结果开始,列和行如何?然后发布您尝试的查询。