TSQL - 选择内的While循环?

Posted

技术标签:

【中文标题】TSQL - 选择内的While循环?【英文标题】:TSQL - While loop within select? 【发布时间】:2012-08-20 01:19:16 【问题描述】:

在 SQL 服务器中

好的,所以我正在使用一个数据库表,其中行可以有父行,然后可以有自己的父行。我需要选择根“行”。我不知道最好的方法。

有一个名为 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

我知道语法很糟糕,但希望我能让您了解我想要实现的目标。

【问题讨论】:

所以我猜ParentReleaseId 等于零的版本不止一个? 你是说 Releases 表是分层的,例如 Release X 有一个前任,然后那个版本有它自己的前任,等等?那么问题是要找到在指定日期内发生的任何以后版本的原始版本? 希望您使用的是 2005 年或之后的版本 - 您能确认一下吗? 是的,有多个父版本 = 0。大卫是的,你有这个权利。我在 2008 年,达米安 看起来您在下面的递归 CTE 答案中朝着正确的方向迈出了一大步。祝你好运! 【参考方案1】:

这是一个可能有用的例子:

此查询正在获取树的较低元素,并搜索到父​​级的父级。 就像我的表中有 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 打败我。干得好:) 谢谢,我这周经常使用这些“算法”:) 是的,它不只是 4 个级别或只是 3 个或什么。它是递归的,向上搜索。我只是写了一个小例子。 顺便说一句,如果有人想测试它,这里是一个 sqlFiddle:sqlfiddle.com/#!3/ad1f2/5(24.08.2012 有效) 谢谢,这将使我的查询更容易应用。【参考方案2】:

类似的东西

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

和小提琴:http://sqlfiddle.com/#!3/a5fa1/1/0

【讨论】:

我认为 CTE 的锚成员将不得不处理 OP 示例查询的日期约束,不是吗? 据我了解,之前选择了起始值,日期限制将在该选择上。【参考方案3】:

使用 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

我现在的问题是我想遍历所有@ID(该代码中的 905)并将每条记录加入到结果中

【讨论】:

以上是关于TSQL - 选择内的While循环?的主要内容,如果未能解决你的问题,请参考以下文章

while循

4_while循环结构和break&continue

循环结构 while 和 do while 方法使用

while循环

循环语句之while循环

java循环语句while与do-while