2015-05-29 3 views
7

Мой босс дал мне один стол.Рекурсия на много разных таблиц родителям для ребенка родителям

 
Related_Items_Table 

Item  | Accessory 
--------------------- 
TV   | Antennae 
TV   | Power Cord 
TV   | Remote 
Laptop  | Power Cord 
Laptop  | Carrying Case 
Camera  | Carrying Case 
Camera  | Lens 
iPod  | Headphones 

Лучший способ описать то, что хочет мой босс для достижения результатов, - это пройти процесс.

  1. Пользователь ищет телевизор.

  2. Телевизор и аксессуары для телевизора Антенны, шнур питания & Пульт дистанционного управления.

  3. Аксессуары Антенны, шнур питания & Пульт дистанционного поиска теперь используется для определения других связанных вопросов. Шнур питания также является аксессуаром для ноутбука. Антенны & Пульт дистанционного управления не является аксессуарами для других предметов.

  4. Элемент Ноутбук теперь используется, чтобы найти аксессуары этого предмета, которые являются шнуром питания & Чехол.

  5. Аксессуары Шнур питания & Футляр для переноски теперь используется для определения других связанных вопросов. Шнур питания не находит новых предметов (мы уже знаем Шнур питания связан с телевизором & Ноутбук). Чехол также является аксессуаром для камеры.

  6. Элемент Камера теперь используется, чтобы найти аксессуары этого предмета, которые - Сумка для переноски & Объектив.

  7. Аксессуары Сумка для переноски & Объектив теперь используется, чтобы найти другие изделия . Чехол & Объектив не найден новый товар (уже знает, что кейс переносится с ноутбуком).

  8. Для поиска в поисковой сети не найдено предметов. Окончательный список вернулся.

 
Final List 

Item  | Accessory 
--------------------- 
TV   | Antennae 
TV   | Power Cord 
TV   | Remote 
Laptop  | Power Cord 
Laptop  | Carrying Case 
Camera  | Carrying Case 
Camera  | Lens 

Что такое лучший способ справиться с этой проблемой? Я не уверен, какая правильная терминология была бы для этого, поэтому, возможно, я пропустил ее в своих поисках. Любые советы приветствуются.

+2

Не разрешается без цикла. Это бесконечная рекурсия. –

ответ

0

Я хотел бы сделать что-то вроде этого pesudocode: псевдокод

insert into Final_List 
all the records that match the item in Related_Items_Table 

WHILE 1=1 
BEGIN 
    Insert into Final List 
    select NextLevel.* 
    from Related_Items_Table 
    join Related_Items_Table NextLevel 
    on Related_Items_Table.Accessory = NextLevel.Item 
    where the nextlevel.item and nextlevel.accesory not already in Final List 
    if @@Rowcount = 0 
     break 
END 
0

Брайана Пресслера является довольно близко, за исключением нескольких проблем с стыками. Вот что я думаю, что это выглядит следующим образом:

-- The sample data from the problem. 
declare @SearchString varchar(32) = 'TV'; 
declare @RelatedItemsTable table 
(
    [Item] varchar(32), 
    [Accessory] varchar(32) 
); 
insert @RelatedItemsTable values 
    ('TV', 'Antennae'), 
    ('TV', 'Power Cord'), 
    ('TV', 'Remote'), 
    ('Laptop', 'Power Cord'), 
    ('Laptop', 'Carrying Case'), 
    ('Camera', 'Carrying Case'), 
    ('Camera', 'Lens'), 
    ('iPod', 'Headphones'); 

-- This table will hold your results. 
declare @SearchResults table 
(
    [Item] varchar(32), 
    [Accessory] varchar(32) 
); 

-- Base case: look for any item or accessory that matches the search string. 
-- I'm not sure whether you want to search items only or accessories also; 
-- adjust as needed. 
insert @SearchResults 
select * 
from 
    @RelatedItemsTable 
where 
    [Item] like @SearchString or 
    [Accessory] like @SearchString; 

while @@rowcount > 0 
begin 
    -- The recursive case: look for new records where... 
    insert @SearchResults 
    select 
     [New].[Item], 
     [New].[Accessory] 
    from 
     @RelatedItemsTable [New] 
     inner join @SearchResults [Old] on 
      -- ... the new record is an item using the same kind of accessory as 
      -- an existing item, or... 
      [New].[Accessory] = [Old].[Accessory] or 

      -- ... the new record is an accessory for the same kind of item as an 
      -- existing accessory, and... 
      [New].[Item] = [Old].[Item] 
    where 
     -- ... this record doesn't yet appear in the result set. 
     not exists 
     (
      select 1 
      from 
       @SearchResults [Existing] 
      where 
       [Existing].[Accessory] = [New].[Accessory] and 
       [Existing].[Item] = [New].[Item] 
     ); 
end; 

select * from @SearchResults; 

SQL Server имеет механизм рекурсивных запросов самой recursive CTE бут я не смог реализовать этот пример, используя один из тех, что я не мог реализовать NOT EXISTS часть вышеуказанного запроса.

0

Я не мог сделать это с помощью CTE, как я уже сказал.Причина, почему объясняется здесь: Prevent recursive CTE visiting nodes multiple times

Так вот старый способ моды

DECLARE @MyTable TABLE(Item NVARCHAR(50), Accessory NVARCHAR(50)) 
DECLARE @Result TABLE(Item NVARCHAR(50), Accessory NVARCHAR(50), LinkedItem NVARCHAR(50), Done int) 

INSERT INTO @MyTable 
VALUES 
('TV', 'Antennae'), 
('TV', 'Power Cord'), 
('TV', 'Remote'), 
('Laptop', 'Power Cord'), 
('Laptop', 'Carrying Case'), 
('Camera', 'Carrying Case'), 
('Camera', 'Lens') 


DECLARE @NbIteration INT = 0 

INSERT INTO @Result 
SELECT t.Item, 
     t.Accessory, 
     LinkedItem.Item, 
     @NbIteration     
FROM @MyTable AS t 
LEFT JOIN @MyTable AS LinkedItem ON t.Accessory = LinkedItem.Accessory 
WHERE t.Item = 'TV' 


WHILE(@@ROWCOUNT > 0) 
BEGIN 
    SELECT @NbIteration = @NbIteration + 1 

    INSERT INTO @Result 
    SELECT t.Item, 
      t.Accessory, 
      LinkedItem.Item, 
      @NbIteration   
    FROM @Result AS r 
    INNER JOIN @MyTable AS t ON r.LinkedItem = t.Item 
    LEFT JOIN @MyTable AS LinkedItem ON t.Accessory = LinkedItem.Accessory 
    WHERE r.Done = @NbIteration - 1 
    AND NOT EXISTS(SELECT TOP 1 1 FROM @Result AS Sub WHERE t.Item = Sub.Item) --don't go back to records already done 

END 

SELECT DISTINCT Item, Accessory 
FROM @Result 
0

Если вы не прочь использовать заявление GOTO для зацикливания вы пытаетесь достичь, вот решение:

DECLARE @search VARCHAR(50) = 'TV' 

--Get initial resultset 
DECLARE @table TABLE (item VARCHAR(50), accessory VARCHAR(50)) 
INSERT INTO @table 
SELECT 
    items.* 
FROM 
    items 
WHERE 
    item LIKE @search 

--declare the variables used for checking if we have any new results 
DECLARE @intCount INT = (SELECT COUNT(*) FROM @table) 
DECLARE @intNewCount INT = (SELECT COUNT(*) FROM @table) 

--The infamous GOTO label 
START: 
    --Store the count of items 
    SET @intCount = (SELECT COUNT(*) FROM @table) 

    --Insert any matching rows for accessory = accessory, excluding ones already added 
    INSERT INTO @table 
     (item, accessory) 
    SELECT 
     item, accessory 
    FROM 
     items 
    WHERE 
     accessory IN (SELECT accessory FROM @table) 
    AND NOT EXISTS(SELECT TOP 1 1 FROM @table t WHERE t.item = items.item AND t.accessory = items.accessory) 

    --Now Insert any matching rows for item = item, excluding ones already added 
    INSERT INTO @table 
     (item, accessory) 
    SELECT 
     item, accessory 
    FROM 
     items 
    WHERE 
     item IN (SELECT item FROM @table) 
    AND NOT EXISTS(SELECT TOP 1 1 FROM @table t WHERE t.item = items.item AND t.accessory = items.accessory) 

    --Set the new count 
    SET @intNewCount = (SELECT COUNT(*) FROM @table) 
--Check if there's been any added during this iteration, if there are, repeat! 
IF @intCount <> @intNewCount GOTO START; 

--Finished 
SELECT * FROM @table 

Я вижу большинство других ответов есть время цикла, думал, что я просто смешать его :) Испытано в SQL2008

1

похоже, ваши таблицы Presen ts - неориентированный граф, и вам нужно пройти этот график, начиная с искомого пользователя Item.

Рассмотрите возможность использования breadth-first search (BFS) algorithm.

Каждый посещенный узел является результирующим списком, в котором вы нуждаетесь.

+0

Хотя эта ссылка может ответить на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [От обзора] (/ review/low-quality-posts/13703724) – techspider

+0

@techspider: ответ, дающий название хорошо известного алгоритма, ссылку на его более полное описание и некоторые примечания о том, почему и как это делается применимо, не имеет никакого смысла «только для ссылок». –

Смежные вопросы