SQL Server 查找两列之间的链

Moh*_*sen 0 sql-server

我有一个这样的表:

from | to
-----+-----
 23  | 24
 24  | 25
 25  | 27
 27  | 30
 45  | 46
 46  | 47
 50  | 52
 53  | 60
Run Code Online (Sandbox Code Playgroud)

我需要一个 SQL Server 查询来检测链并返回每个链中的最小(从)和最大(到)(也是具有一条记录的链):

from | to
-----+-----
 23  | 30
 45  | 47
 50  | 52
 53  | 60
Run Code Online (Sandbox Code Playgroud)

JNe*_*ill 5

这是一种使用递归 CTE 的方法。

CREATE TABLE #chainLinks(linkFrom INTEGER, linkTo INTEGER);
INSERT INTO #chainLinks VALUES (23,24);
INSERT INTO #chainLinks VALUES (24,25);
INSERT INTO #chainLinks VALUES (25,27);
INSERT INTO #chainLinks VALUES (27,30);
INSERT INTO #chainLinks VALUES (45,46);
INSERT INTO #chainLinks VALUES (46,47);
INSERT INTO #chainLinks VALUES (50,52);
INSERT INTO #chainLinks VALUES (53,60);

WITH reccte AS
(
    /*Recursive Seed*/
    SELECT linkFrom AS chainStart,
        linkFrom,
        linkTo,
        0 as links
    FROM #chainLinks as chainLinks
    WHERE linkFrom NOT IN (SELECT DISTINCT linkTo FROM #chainLinks)

    UNION ALL

    /*Recursive Term*/
    SELECT 
        reccte.chainStart,
        chainLinks.linkFrom,
        chainLinks.linkTo,
        links + 1
    FROM reccte
        INNER JOIN #chainLinks as chainLinks ON reccte.linkTo = chainLinks.linkFrom
)
SELECT chainStart, linkTo AS chainEnd
FROM
    (
        SELECT chainStart, linkFrom, linkTo, links, ROW_NUMBER() OVER (PARTITION BY chainStart ORDER BY links DESC) AS rn
        FROM reccte 
    )subrn
WHERE rn = 1;
Run Code Online (Sandbox Code Playgroud)

递归 CTE 分为两部分

  1. UNION递归种子 - 这是我们确定表中哪些记录开始递归的部分。在这里我们想要任何linkFrom不是linkTo
  2. 递归术语 - 这是我们连接调用回原始表的UNIONcte的下面的部分。reccteCTE 的这一部分会一遍又一遍地迭代,直到连接失败。

在这里,我们还跟踪它,links它只是我们为获取输出记录而经历的迭代次数的计数器。links我们保留每个起点的最大数量chainStart

这是工作示例: https: //rextester.com/JWUW57837