How to stop recursion in a CTE?

别说谁变了你拦得住时间么 提交于 2019-12-24 02:02:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!