Sql-server – How to get all connected values as a single column

cterecursivesql serversql-server-2008

I'm trying to use CTE recursion.
This is my scenario SQL Fiddle.
It is a simple tree structure:

CREATE TABLE [dbo].[AL](
    [IdAL] [int] IDENTITY(1,1) NOT NULL,
    [ID1] [int] NOT NULL,
    [ID2] [int] NOT NULL,
 CONSTRAINT [PK_AL] PRIMARY KEY CLUSTERED 
    (
      [IdAL] ASC
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
            ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] ;

INSERT INTO AL (ID1, ID2)
VALUES (1092, 284917), 
       (1092, 248957), 
       (1092, 789475),
       (   1, 789475), 
       (   1,      2), 
       (   3,      2), 
       (   6,      4) ;

Simply put, the user gives me an id (e.g. 1092). I would recursively run all rows in the table and do the merge of the id (ID1 + ID2) starting with the id provided by the user.

I would like to get something like this (in just one column called ID):

ID
1092, 
284917,
248957,
789475,
1,
2,
3

Note that id 4 and 6 are not in the result list because there is no node that points to these ids.

Best Answer

this is my solution. As I mentioned in a previous comment, it's not the prettiest solution stylistically, but it works.

DECLARE @Id int = 1092

DECLARE @i                      INT = 0,
    @IdToProcess    INT = 0

DECLARE @t TABLE    (   Id  INT,
                    Processed   BIT
                )

INSERT INTO @t (Id, Processed)
VALUES (@Id, 0)

WHILE   (1 = 1 OR @i <= 100)
BEGIN
 SET @i = @i +1
SET @IdToProcess = 0

SELECT  @IdToProcess = MIN(Id)
FROM    @t
WHERE   Processed = 0

SET @IdToProcess = ISNULL(@IdToProcess, 0)

IF @IdToProcess <= 0
BEGIN
    BREAK
END

INSERT INTO @t (Id, Processed)
SELECT  AL.Id2, 0
FROM    dbo.AL AL
WHERE   AL.Id1 = @IdToProcess
        AND NOT EXISTS (SELECT 1 FROM @t T WHERE T.Id = AL.Id2)
UNION
SELECT  AL.Id1, 0
FROM    dbo.AL AL
WHERE   AL.Id2 = @IdToProcess
        AND NOT EXISTS (SELECT 1 FROM @t T WHERE T.Id = AL.Id1)

UPDATE  @t
SET     Processed = 1
WHERE   Id = @IdToProcess
END

SELECT * FROM @T