【问题标题】:SQL Server Recursion QuestionSQL Server 递归问题
【发布时间】:2011-01-10 15:57:07
【问题描述】:

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

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 关系将存储在 DB 中:

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 对。那有意义吗?

【问题讨论】:

  • 我在任何一侧都没有看到任何一对。你是在暗示还有一个你没有讨论过的等级和顺序吗?
  • 4-5 对如何属于链接 1?
  • Link下的数字是什么意思?我希望它是一个自动增量。你能退后一步,提供一个明确的用例或业务需求吗?很难理解您需要什么...
  • 一些用于创建表的 DDL 语句会很有帮助,包括表之间的关系。

标签: sql sql-server-2005 tsql recursion cursor


【解决方案1】:

我怀疑这个问题已经死了,但是这里有。

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

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

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

【讨论】:

    猜你喜欢
    • 2013-01-10
    • 1970-01-01
    • 2011-01-22
    • 2014-12-19
    • 2017-02-02
    • 2012-12-05
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多