2015-05-29 2 views
7

Mein Chef hat mir eine einzige Tabelle gegeben.Rekursion auf eine viele zu viele Tabelle Eltern zu Kind zu Eltern

 
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 

Der beste Weg zu beschreiben, was mein Chef für Ergebnisse will, ist durch den Prozess zu gehen.

  1. Der Benutzer sucht nach TV.

  2. TV gefunden und das Zubehör für TV sind Antennen, Netzkabel & Remote.

  3. Das Zubehör Antennen, Netzkabel & Remote werden jetzt verwendet, um andere verwandte Artikel zu finden. Netzkabel ist auch ein Zubehör für Laptop. Antennen & Fernbedienung ist kein Zubehör für andere Gegenstände.

  4. Der Artikel Laptop wird jetzt verwendet, um das Zubehör dieses Artikels zu finden, die sind Netzkabel & Tragetasche.

  5. Das Zubehör Netzkabel & Tragetasche werden jetzt verwendet, um andere verwandte Artikel zu finden. Netzkabel findet keine neuen Artikel (wir wissen bereits Netzkabel ist mit TV & Laptop verbunden). Tragetasche ist auch ein Zubehör für Kamera.

  6. Der Artikel Kamera wird jetzt verwendet, um Zubehör dieses Artikels zu finden, die sind Tragetasche & Objektiv.

  7. Das Zubehör Tragetasche & Linse werden jetzt verwendet, um andere verwandte Artikel zu finden. Tragetasche & Objektiv finden Sie keine neuen Artikel (wir bereits wissen, Tragetasche ist mit Laptop verbunden).

  8. Es werden keine neuen Elemente gefunden, um die Suchkette fortzusetzen. Endgültige Liste zurückgegeben.

 
Final List 

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

Was ist der beste Weg, um dieses Problem zu umgehen? Ich bin nicht sicher, was die korrekte Terminologie für dieses sein würde, also verpasste ich es vielleicht in meinen Suchen. Jeder Rat wird geschätzt.

+2

Nicht lösbar ohne Schleife. Es ist eine unendliche Rekursion. –

Antwort

0

würde ich so etwas wie dieses pesudocode tun:

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

Brian Pressler Pseudo-Code ziemlich nahe ist, mit dem schließt sich ein paar Probleme speichern. Hier ist, was ich denke, das wie folgt aussieht:

-- 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 hat einen Mechanismus für rekursive Abfragen-the recursive CTE -aber ich nicht in der Lage war, dieses Beispiel implementieren einen von denen verwenden, weil ich nicht die NOT EXISTS implementieren könnte Teil der obigen Abfrage.

0

Ich könnte es nicht mit CTE tun, wie ich schon sagte.Grund, warum hier erklärt: Prevent recursive CTE visiting nodes multiple times

So, hier ist eine alte Mode Weise

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

Wenn Sie eine Lösung nicht abgeneigt sind sind Sie versuchen, zu verwenden hier eine GOTO-Anweisung für die Schleife zu erreichen:

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 

ich die meisten der anderen Antworten sehen eine while-Schleife, dachte ich würde es nur in SQL2008 getestet mischen :)

1

es sieht aus wie sie Ihren Tisch presen ts ein ungerichtetes Diagramm und Sie müssen dieses Diagramm durchlaufen, beginnend mit dem durchsuchten Objektbenutzer.

Verwenden Sie breadth-first search (BFS) algorithm.

Jeder besuchte Knoten ist eine Ergebnisliste, die Sie benötigen.

+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - [Aus Review] (/ review/low-quality-posts/13703724) – techspider

+0

@techspider: Eine Antwort, die den Namen eines bekannten Algorithmus gibt, einen Link zu einer ausführlicheren Beschreibung und einige Hinweise, warum und wie es ist anwendbar ist in keinem möglichen Sinne "nur Link". –