Вопрос рекурсии SQL Server - PullRequest
0 голосов
/ 29 января 2010

Мне нужно создать ссылки между парами элементов и строками пар элементов:

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 будет сохранено в БД как:

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 пар. Имеет ли это смысл?

1 Ответ

0 голосов
/ 19 января 2012

Я подозреваю, что этот вопрос мертв, но здесь идет.

Судя по комментариям, возможно, было некоторое недопонимание того, что здесь делается. Похоже, что таблица ссылок генерируется парами. В сущности, Ссылки представляют собой раздел Предметов, основанный на связи «в паре с».

Вот частичный ответ (в том смысле, что он создает таблицу ссылок, как показано, но, возможно, не самый эффективный). Возможно, кто-то может улучшить это.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...