问题
I have a database table which looks like this:
ID | PredecessorID | Data
-------------------------------------|--------------------------------------|-----------------
43b1e103-d8c6-40f9-b031-e5d9ef18a739 | null | ...
55f6951b-5ed3-46c8-9ad5-64e496cb521a | 43b1e103-d8c6-40f9-b031-e5d9ef18a739 | ...
3eaa0889-31a6-449d-a499-e4beb9e4cad1 | 55f6951b-5ed3-46c8-9ad5-64e496cb521a | ...
I know that I can use a (recursive) common table expression (CTE) to get a sorted list of my data:
WITH cte (ID, Data)
AS
(
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID IS NULL
UNION ALL
-- other cases
SELECT x.ID, x.Data
FROM MyTable as x
INNER JOIN cte
ON x.PredecessorID = cte.ID
)
SELECT * FROM cte
While this works, if I want to get the entire table, I wonder how to only get a part of the table, say, everything between from ID x
up to ID y
.
Getting the lower bound right is easy (I assume): Simply change the WHERE
criteria of the base case to the ID I want to start with:
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID='...'
But what about the upper bound? How do I tell the CTE to stop recursing once the record with the ID y
has been reached?
回答1:
Since you are iterating here and have the cte's last id that it picked up available in your recursive term you can just filter out results where the last iteration hit 'y'
WITH cte (ID, Data)
AS
(
-- base case
SELECT x.ID, x.Data
FROM MyTable AS x
WHERE x.PredecessorID IS NULL
UNION ALL
-- other cases
SELECT x.ID, x.Data
FROM MyTable as x
INNER JOIN cte
ON x.PredecessorID = cte.ID
WHERE cte.id <> 'y'
)
SELECT * FROM cte;
Note that if your x
id has many branches, some of which don't lead to 'y' then those branches will keep iterating until they hit their natural end. Only branch leading to y
will be prematurely stopped here.
回答2:
I'm just curious if you could simply modify the recursive select part to stop when id becomes y (assuming that there is only 1 path from x to y), similar to this:
with recursive cte (count) as (
select 1 as count
union all
select count + 1 from cte where count != 100
)
select * from cte;
来源:https://stackoverflow.com/questions/52654255/how-to-stop-recursion-in-a-cte