使用WITH循环SQL中的一组数据

时间:2015-03-11 16:45:03

标签: sql sql-server tsql loops

鉴于以下字段,我试图循环到整个迭代集的第一次迭代。

+-------------------+----------------------+------------------------+
|           id      |     nextiterationId  |      iterationCount    | 
+-------------------+----------------------+------------------------+
|           110001  |             110002   |      0                 |
|           110002  |             110003   |      1                 |
|           110003  |             110004   |      2                 |
|           110004  |             1        |      3                 |

因此,如果我使用id字段的某个值调用SP /函数,我需要它返回给定的id的先前迭代,直到iterationCount = 0

因此,如果我使用110003的ID(将其作为参数发送),它首先要查询的是id字段nextIterationID 110003。那将是第一个循环。

由于iterationCount还不是0,它会保持循环。然后它将根据第一个循环确定查找nextIterationID110002的id,因此第二个循环将找到110001的“id”并返回它。并且由于记录iterationCount = 0,它将停止循环。

如果我使用110003调用SP /函数,这是第3次迭代,并且它不会返回110004,第4次迭代,这没关系。我只需要它就可以回到id。

前段时间我使用WITH和也许WHILE以某种方式使用它们,但我现在不记得如何做到这一点。我需要以某种方式返回的格式,以便我可以在更大的SELECT语句中使用它。

1 个答案:

答案 0 :(得分:6)

这是一个递归的cte解决方案。如果需要任何调整,请告诉我。

--Throwing your table into a temp table
CREATE TABLE #yourTable (ID INT,NextIterationID INT,IterationCount INT)
INSERT INTO #yourTable
VALUES
    (110001,110002,0),
    (110002,110003,1),
    (110003,110004,2),
    (110004,1,3)

--Now for the actual work
--Here is your parameter
DECLARE @param INT = 110003;

--Recursive CTE
WITH yourCTE
AS
(
    --Initial Row
    SELECT  ID,
            NextIterationID,
            IterationCount
    FROM    #yourTable
    WHERE   NextIterationID = @param

    UNION ALL

    --Finding all previous iterations
    SELECT  #yourTable.*
    FROM    #yourTable
    INNER JOIN yourCTE
    ON yourcte.ID = #yourTable.NextIterationID
    --Where clause is not really necessary because once there are no more previous iterations, it will automatically stop
    --WHERE yourCTE.IterationCount >= 0
)

SELECT *
FROM yourCTE

--Cleanup
DROP TABLE #yourTable

结果:

ID          NextIterationID IterationCount
----------- --------------- --------------
110002      110003          1
110001      110002          0