SQL 服务器:我怎样才能实现这个...可能使用递归函数?

SQL Server : how can I achieve this...possibly with a recursive function?

我有下面的例子table:

每个customer_number可能有一个或多个debtor_id,反之亦然每个debtor_id可能有一个或多个customer_number。现在我基本上需要一种方法来从任何给定的 customer_number 或 debtor_id

中检索所有 customer_numbers 或 debtor_ids

更具体的例子:

假设您想知道连接到 debtor_id 24.

的所有 customer_number

所以最后当输入 debtor_id 24 时,您希望检索到 customer_number customer10、customer11 和 customer12 作为结果。

我知道它可能需要多个自连接,但它需要灵活并针对任何给定的“深度”动态工作。我的第一个想法是,这闻起来很像递归。基本上类似于“保持自连接,直到没有新的 customer_number 或 debtor_id 返回”

我对递归没有太多经验,编写SQL函数也是如此:-(

有人对此有一些提示或有用的建议吗?

生成相同内容的示例代码 table:

DECLARE @customers TABLE
                   (
                       customer_number VARCHAR(16),
                       debtor_id INT
                   );

INSERT INTO @customers SELECT 'customer10', 20;
INSERT INTO @customers SELECT 'customer10', 22;
INSERT INTO @customers SELECT 'customer11', 22;
INSERT INTO @customers SELECT 'customer11', 23;
INSERT INTO @customers SELECT 'customer12', 23;
INSERT INTO @customers SELECT 'customer12', 24;
INSERT INTO @customers SELECT 'customer15', 30;
INSERT INTO @customers SELECT 'customer16', 31;
INSERT INTO @customers SELECT 'customer16', 32;
INSERT INTO @customers SELECT 'customer21', 31;
INSERT INTO @customers SELECT 'customer21', 35;

SELECT * 
FROM @customers;

您可以使用如下所示的递归 CTE 来完成此操作

-- Find all customers for debtor
WITH CTE AS (
    SELECT [debtor_id] AS [Root],
        [debtor_id],
        [customer_number],
        CAST('' AS VARCHAR(2000)) AS [Path]
    FROM @customers AS [b]
    UNION ALL
    SELECT [b].[Root],
        [c].[debtor_id],
        [d].[customer_number],
        CAST([b].[Path] + CAST([c].[debtor_id] AS VARCHAR(10)) + '||' AS VARCHAR(2000)) AS [Path]
    FROM [CTE] AS [b]
        INNER JOIN @customers AS [c] ON [b].[customer_number] = [c].[customer_number]
        INNER JOIN @customers AS [d] ON [d].[debtor_id] = [c].[debtor_id]
    WHERE [c].[debtor_id] != [b].[Root]
        AND [Path] NOT LIKE '%' + CAST([c].[debtor_id] AS VARCHAR(10)) + '||%'
)
SELECT DISTINCT
    [customer_number]
FROM [CTE] AS [c]
WHERE [Root] = 24;

-- Find all debtors for customer
WITH CTE AS (
    SELECT [customer_number] AS [Root],
        [debtor_id],
        [customer_number],
        CAST('' AS VARCHAR(2000)) AS [Path]
    FROM @customers AS [b]
    UNION ALL
    SELECT [b].[Root],
        [d].[debtor_id],
        [c].[customer_number],
        CAST([b].[Path] + [c].[customer_number] + '||' AS VARCHAR(2000)) AS [Path]
    FROM [CTE] AS [b]
        INNER JOIN @customers AS [c] ON [b].[debtor_id] = [c].[debtor_id]
        INNER JOIN @customers AS [d] ON [d].[customer_number] = [c].[customer_number]
    WHERE [c].[customer_number] != [b].[Root]
        AND [Path] NOT LIKE '%' + [c].[customer_number] + '||%'
)
SELECT DISTINCT [debtor_id]
FROM [CTE] AS [c]
WHERE [Root] = 'customer10';