TSQL - 在SELECT语句中使用While循环?

9

在SQL Server中

好的,我正在处理一张包含父子行的数据库表格,其中父行可以有自己的父行。我需要选择根'行'。 我不知道最好的方法是什么。

有一个名为ParentId的字段,它将该行与具有该ID的行链接起来。 当ParentId = 0时,它是根行。

这是我的查询现在:

SELECT Releases.Name,WorkLog.WorkLogId 

FROM WorkLog,Releases
WHERE
Releases.ReleaseId = WorkLog.ReleaseId
and WorkLogDateTime >= @StartDate
and WorkLogDateTime <= @end

我不需要子版本的发布名称,我只需要根版本的发布名称,所以我想选择像这样的While循环结果:

WHILE (ParentReleaseId != 0)
BEGIN
@ReleaseId = ParentReleaseId
END

Select Release.Name
where Release.RealeaseId = @ReleaseId

我知道这个语法很恶心,但是希望我给你的想法能够让你明白我想要实现什么。


1
所以我猜测有不止一个ParentReleaseId等于零的版本发布? - AakashM
你是说Releases表是分层的,例如Release X有一个前任,然后该发布版有它自己的前任,以此类推吗?因此问题是要找到在指定日期范围内发生的任何后续发布版的原始发布版? - David W
希望你使用的是2005年或之后的版本 - 你能确认一下吗? - Damien_The_Unbeliever
是的,有不止一个父版本 release = 0。David,是的,你说得对。我在使用2008版本,Damien。 - ryan jenkins
看起来你在下面的递归CTE答案中得到了很好的推动。祝你好运! - David W
3个回答

9
这里有一个例子,可能会有用:
这个查询获取树形结构的底层元素,并搜索到其父级的父级。比如我的表格中有4个层级 -> 类别7->5,5->3,3->1。如果我给它数字5,它会找到数字1,因为这是树形结构的顶层。
(通过改变最后的选择语句,你可以获取一路上所有的父级。)
DECLARE @ID int

SET @ID = 5;

WITH CTE_Table_1
(
  ID,
  Name,
  ParentID
)
AS(
  SELECT 
   ID,
   Name,
   ParentID
  FROM Table_1
  WHERE ID = @ID

 UNION ALL

 SELECT 
  T.ID,
  T.Name,
  T.ParentID
 FROM Table_1 T
 INNER JOIN CTE_Table_1 ON CTE_Table_1.ParentID = T.ID
)

SELECT * FROM CTE_Table_1 WHERE ParentID = 0

糟糕,使用 CTE 比我先了。干得好 :) - David W
谢谢,我这周经常使用这些“算法” :) - András Ottó
是的,它不仅仅是4个级别或3个级别之类的。它是递归的,向上搜索。我只是写了一个小例子。 - András Ottó
2
顺便说一句,如果有人想测试一下,这里是一个sqlFiddle链接: http://www.sqlfiddle.com/#!3/ad1f2/5 (截至2012年8月24日有效) - András Ottó
谢谢,这将使我更容易应用到我的查询中。 - ryan jenkins

1

类似这样的东西

with cte as
(
  select id,parent_id from t where t.id=@myStartingValue
  union all
  select t.id,t.parent_id
  from cte
  join t on cte.parent_id = t.id where cte.parent_id<>0
 )
select * 
from cte
join t on cte.id=t.id where cte.parent_id = 0

并且使用 fiddle:http://sqlfiddle.com/#!3/a5fa1/1/0


我认为CTE的锚定成员将不得不处理OP示例查询的日期约束,是吗? - David W
据我所了解,起始值是先选定的,日期约束将基于该选择。 - Dumitrescu Bogdan

0
使用Andras的方法,我编辑了最后的选择代码,直接返回根发布的ID。
WITH cte_Releases
( 
  ReleaseId, 
  ParentReleaseID 
) 
AS( 
  SELECT  
   ReleaseId, 
   ParentReleaseID 
  FROM Releases
  Where ReleaseId = 905

 UNION ALL 

 SELECT  
  R.ReleaseId, 
  R.ParentReleaseID 
 FROM Releases R
 INNER JOIN cte_Releases ON cte_Releases.ParentReleaseID = R.ReleaseId
) 

SELECT max(ReleaseId) as ReleaseId, min(ReleaseId) as RootReleaseId FROM cte_Releases

我现在的问题是,我想遍历所有的@IDs(在那段代码中为905),并将每个记录连接到结果中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接