2016-10-12 4 views
1
FromID    ToID  
-------------- ----------  
    1    2    
    2    3     
    3    4     
    5    6     
    6    7     
    9    10 

Ich mag würde rekursive Abfrage in SQL Server 2008 verwenden, um eine Ausgabe alsSQL Server 2008 rekursive Abfrage

FromID    Path 
1      1,2,3,4 
5      5,6,7           
9      9,10 

Ich habe zu erstellen versuche, wie unten eine SQL-Anweisung mit Bezug auf Online-Beispiele zu konstruieren

;WITH items AS (
    SELECT FromID 
    , CAST(FromID AS VARCHAR(255)) AS Path 
    FROM tablex 
    UNION ALL 
    SELECT i.FromID 
    , CAST(Path + '.' + CAST(i.FromID AS VARCHAR(255)) AS VARCHAR(255)) AS Path 
    FROM tablex i 
    INNER JOIN items itms ON itms.FromID = i.ToID 
) 
SELECT * 
FROM items 
ORDER BY Path 

Allerdings funktioniert oben nicht. Irgendwelche Ideen?

+0

So würde 2-3 nicht seine eigene Reihe bekommen, aber 6-9 würde, weil Sie hatte 6-7 vorher? –

+0

Hallo, um zu vereinfachen, habe ich 6-9 herausgenommen. Es ist wie eine Baumstruktur, wobei 1,5,9 die Wurzel-ID ist. Ich brauche die Kinder für jede Wurzel ID – user3050151

Antwort

1

Es ist mir nicht ganz klar, warum Ihre erwartete Ausgabe ist, was es ist. Der Pfad von 6-10 ist nicht der vollständige Pfad zu 10: Dieser Pfad beginnt bei ID 5. Ich habe ein Beispiel geschrieben, das den vollständigen Pfad ausgibt, um zu veranschaulichen, wie Sie das tun würden. Wenn Sie wirklich möchten, dass es aus irgendeinem Grund bei 6 beginnt, geben Sie bitte klar die Regel an, die bestimmt, welche Knoten als Startpunkte in der Ergebnismenge angezeigt werden sollen.

Ich habe festgestellt, dass jede ID in Ihren Beispieldaten genau einen Vorgänger aber möglicherweise mehrere Nachfolger hat. Aus diesem Grund habe ich gewählt, die Knoten, die Endpunkte sind, zu identifizieren und dann rückwärts zu den Startpunkten zu arbeiten. Hoffentlich reichen die folgenden Kommentare aus, um den Rest von dem zu erklären, was vor sich geht.

declare @TableX table (FromID int, ToID int); 
insert @TableX values (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (6, 9), (9, 10); 

with PathCTE as 
(
    -- BASE CASE 
    -- Any ID that appears as a "to" but not a "from" is the endpoint of a path. This 
    -- query captures the ID that leads directly to that endpoint, plus the path 
    -- represented by that one row in the table. 
    select 
     X1.FromID, 
     [Path] = convert(varchar(max), X1.FromID) + ',' + convert(varchar(max), X1.ToID) 
    from 
     @TableX X1 
    where 
     not exists (select 1 from @TableX X2 where X2.FromID = X1.ToID) 

    union all 

    -- RECURSIVE CASE 
    -- For every path previously identified, look for another record in @TableX that 
    -- leads to its starting point and prepend that record's from ID to the overall path. 
    select 
     X.FromID, 
     [Path] = convert(varchar(max), X.FromID) + ',' + PathCTE.[Path] 
    from 
     PathCTE 
     inner join @TableX X on PathCTE.FromID = X.ToID 
) 

-- Any ID that appears as a "from" but not a "to" is the starting point of one or more 
-- paths, so we get all results beginning at one of those points. All other output from 
-- PathCTE is partial paths, which we can ignore. 
select * 
from 
    PathCTE 
where 
    not exists (select 1 from @TableX X where PathCTE.FromID = X.ToID) 
order by 
    FromID, [Path]; 

Ausgang:

FromID Path 
1  1,2,3,4 
5  5,6,7 
5  5,6,9,10 
+0

Hallo danke. Ich habe versucht, meine Frage zu vereinfachen. Ich habe tatsächlich 2 Tische. Die zweite Tabelle hat die Koordinaten jedes Knotens. z.B. records 1-coords1, 2-coords2, 3-coords3, 4-coords4, etc .. Ich müsste auch die 2 Tabellen verbinden, so dass ich mit einer Ausgabe enden, wo Feld 'Path' die Koordinaten statt – user3050151

+0

@ user3050151: Das hört sich so an, als sollte es nur eine einfache Änderung an jeder der beiden 'select' Anweisungen sein, die sich im CTE in der obigen Abfrage befinden. Ändern Sie jede 'from'-Klausel, um von' @ TableX' zu Ihrer zweiten Tabelle zu verbinden, und ändern Sie dann die Definition von '[Path]', um das entsprechende Feld aus dieser zweiten Tabelle anstelle von 'X.FromID' zu verwenden. –