SQL Server 递归问题

发布于 2024-08-19 17:01:46 字数 711 浏览 2 评论 0原文

我需要在项目对和项目对行之间创建链接:

ItemA   ItemB
----------------
1       2
1       3
4       5
4       6
6       2  
7       8
9       2
9       10
11      12
11      13
14      15

一对两侧的匹配构成一个链接:

Link  A   B
---------------
1     1   2
1     1   3
1     4   5
1     4   6
1     6   2
2     7   8
1     9   2
1     9   10
3     11  12
3     11  13
4     14  15

链接项目关系将存储在数据库中为:

Link  Item
--------------
1     1
1     2
1     3
1     4
1     5
1     6
1     9
1     10
2     7
2     8
3     11
3     12
3     13
4     14
4     15

关于最有效方法的任何想法( SQL Server 2005)?

ItemA = 1 和 ItemB = 2 是第一对。该集中有 11 对要处理。这有道理吗?

I need to create links between pairs of items and rows of item pairs:

ItemA   ItemB
----------------
1       2
1       3
4       5
4       6
6       2  
7       8
9       2
9       10
11      12
11      13
14      15

Matching on either side of a pair constitutes a link:

Link  A   B
---------------
1     1   2
1     1   3
1     4   5
1     4   6
1     6   2
2     7   8
1     9   2
1     9   10
3     11  12
3     11  13
4     14  15

The Link-Item relationship will be stored in the DB as:

Link  Item
--------------
1     1
1     2
1     3
1     4
1     5
1     6
1     9
1     10
2     7
2     8
3     11
3     12
3     13
4     14
4     15

Any ideas on the most efficient way to do this (SQL Server 2005)?

ItemA = 1 and ItemB = 2 is the first pair. There are 11 pairs in the set to process. Does that make sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

女皇必胜 2024-08-26 17:01:46

我怀疑这个问题已经死了,但还是这样。

从评论来看,可能对这里所做的事情存在一些误解。看起来链接表是由对生成的。实际上,链接代表基于“配对”关系的项目分区。

这是部分答案(从某种意义上说,它创建了如图所示的链接表,但可能不是最有效的)。也许有人可以改进这一点。

DECLARE @pairs TABLE (ItemA INT, ItemB INT)

INSERT INTO @pairs (ItemA, ItemB) VALUES ( 1,  2)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 1,  3)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 4,  5)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 4,  6)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 6,  2) 
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 7,  8)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 9,  2)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 9, 10)
INSERT INTO @pairs (ItemA, ItemB) VALUES (11, 12)
INSERT INTO @pairs (ItemA, ItemB) VALUES (11, 13)
INSERT INTO @pairs (ItemA, ItemB) VALUES (14, 15)

DECLARE @links TABLE (Link INT, Item INT)

DECLARE @nextItem INT
DECLARE @nextLink INT
SET @nextLink = 0

DECLARE @itemsLeft BIT
SET @itemsLeft = 1

DECLARE @insertCount INT

WHILE @itemsLeft = 1
BEGIN

    -- Get the next Item not already in a link
    SELECT @nextItem = MIN(allItems.Item) 
    FROM (SELECT ItemA AS Item FROM @pairs UNION SELECT ItemB FROM @pairs) AS allItems
    LEFT JOIN @links l ON l.Item = allItems.Item
    WHERE l.Link IS NULL

    SET @nextLink = @nextLink + 1

    IF (@nextItem IS NOT NULL)
    BEGIN

        -- There will be at least 1 new link            
        INSERT INTO @links (Link, Item) VALUES (@nextLink, @nextItem)

        SET @insertCount = 1
        -- Keep going until no new Items found...
        WHILE (@insertCount > 0)
        BEGIN

            INSERT INTO @links (Link, Item)
            SELECT la.Link, p.ItemB
            FROM @pairs p
            INNER JOIN @links la ON la.Item = p.ItemA
            LEFT JOIN @links lb ON lb.Item = p.ItemB
            WHERE lb.Link IS NULL
            SET @insertCount = @@ROWCOUNT

            INSERT INTO @links (Link, Item)
            SELECT lb.Link, p.ItemA
            FROM @pairs p
            INNER JOIN @links lb ON lb.Item = p.ItemB
            LEFT JOIN @links la ON la.Item = p.ItemA
            WHERE la.Link IS NULL
            SET @insertCount = @insertCount + @@ROWCOUNT

        END
    END
    ELSE
        SET @itemsLeft = 0

END

SELECT * FROM @links ORDER BY 1,2

I suspect that this question is dead, but here goes.

Judging by the comments, there may have been some misunderstanding of what is being done here. It looks like the Link table is being generated by the pairs. In effect, the Links represent a partition of the Items based on the relationship "is paired with".

Here is a partial answer (in the sense that it creates the Link table as illustrated but may not be the most efficient). Perhaps somebody can improve on this.

DECLARE @pairs TABLE (ItemA INT, ItemB INT)

INSERT INTO @pairs (ItemA, ItemB) VALUES ( 1,  2)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 1,  3)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 4,  5)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 4,  6)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 6,  2) 
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 7,  8)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 9,  2)
INSERT INTO @pairs (ItemA, ItemB) VALUES ( 9, 10)
INSERT INTO @pairs (ItemA, ItemB) VALUES (11, 12)
INSERT INTO @pairs (ItemA, ItemB) VALUES (11, 13)
INSERT INTO @pairs (ItemA, ItemB) VALUES (14, 15)

DECLARE @links TABLE (Link INT, Item INT)

DECLARE @nextItem INT
DECLARE @nextLink INT
SET @nextLink = 0

DECLARE @itemsLeft BIT
SET @itemsLeft = 1

DECLARE @insertCount INT

WHILE @itemsLeft = 1
BEGIN

    -- Get the next Item not already in a link
    SELECT @nextItem = MIN(allItems.Item) 
    FROM (SELECT ItemA AS Item FROM @pairs UNION SELECT ItemB FROM @pairs) AS allItems
    LEFT JOIN @links l ON l.Item = allItems.Item
    WHERE l.Link IS NULL

    SET @nextLink = @nextLink + 1

    IF (@nextItem IS NOT NULL)
    BEGIN

        -- There will be at least 1 new link            
        INSERT INTO @links (Link, Item) VALUES (@nextLink, @nextItem)

        SET @insertCount = 1
        -- Keep going until no new Items found...
        WHILE (@insertCount > 0)
        BEGIN

            INSERT INTO @links (Link, Item)
            SELECT la.Link, p.ItemB
            FROM @pairs p
            INNER JOIN @links la ON la.Item = p.ItemA
            LEFT JOIN @links lb ON lb.Item = p.ItemB
            WHERE lb.Link IS NULL
            SET @insertCount = @@ROWCOUNT

            INSERT INTO @links (Link, Item)
            SELECT lb.Link, p.ItemA
            FROM @pairs p
            INNER JOIN @links lb ON lb.Item = p.ItemB
            LEFT JOIN @links la ON la.Item = p.ItemA
            WHERE la.Link IS NULL
            SET @insertCount = @insertCount + @@ROWCOUNT

        END
    END
    ELSE
        SET @itemsLeft = 0

END

SELECT * FROM @links ORDER BY 1,2
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文