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循环?的主要内容,如果未能解决你的问题,请参考以下文章