Sql-Server

如何將所有連接值作為單列獲取

  • April 6, 2016

我正在嘗試使用 CTE 遞歸。這是我的場景SQL Fiddle。它是一個簡單的樹形結構:

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) ;

簡單地說,使用者給了我一個 id(例如 1092)。我會遞歸地執行表中的所有行,並從使用者提供的 id 開始合併 id (ID1 + ID2)。

我想得到這樣的東西(在一個名為 ID 的列中):

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

請注意,id 4 和 6 不在結果列表中,因為沒有指向這些 id 的節點。

這是我的解決方案。正如我在之前的評論中提到的,它在風格上不是最漂亮的解決方案,但它確實有效。

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

引用自:https://dba.stackexchange.com/questions/133259