在我正在研究的webapp中,有一个表,其中包含所谓的ProjectItems
。问题是不同类型的项目项目驻留在同一个表中;你可以创建一个项目,一个问题,一个想法和一个反应。使用按位列,类型在[Type]
列中设置。并且每个项目项可以在同一个表中具有父项(由名为fk_Parent
的列定义)。
层次结构如下:
Project
(32)> Question
(1)> Idea
(2)> Reaction
(4)
(我对数据库设置没有任何影响。)
我现在正在创建一个存储过程,用于获取作为参数传递ID的任何项目的根项目项(类型为Project),但到目前为止我感觉有点笨拙:
CREATE PROC [dbo].[spProjectItemGetTopParentId]
@ID INT
AS
DECLARE @parentId INT
SELECT @parentId = fk_Parent FROM tblProjectItem WHERE ID = @ID
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
RETURN @parentId
ELSE
SELECT @parentId = fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
RETURN @parentId
ELSE
SELECT @parentId = fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
RETURN @parentId
ELSE
SELECT @parentId = fk_Parent FROM tblProjectItem WHERE ID = @parentId
IF ((SELECT [Type] FROM tblProjectItem WHERE ID = @parentId) = 32)
RETURN @parentId
ELSE
RETURN 0
GO
我想知道在SQL中是否有任何方法可以递归地执行此操作?还是用其他方法让它更整洁一点?
编辑: 这是包括CTE的SP:
CREATE PROC [dbo].[spTest]
@ID INT
AS
DECLARE @parentId INT;
WITH Parents as (
select ID,Type,fk_Parent from tblProjectItem where ID = @ID
union all
select pi.ID,pi.Type,pi.fk_Parent
from
Parents p
inner join
tblProjectItem pi
on
p.fk_Parent = pi.ID
)
select @parentId = ID from Parents where Type = 32
GO
答案 0 :(得分:1)
是的,recursive CTE可以为您找到:
;WITH Parents as (
select ID,Type,parent_id from tblProjectItem where ID = @ID
union all
select pi.ID,pi.Type,pi.parent_id
from
Parents p
inner join
tblProjectItem pi
on
p.parent_id = pi.ID
)
select @parentId = ID from Parents where Type = 32
作为旁注,我建议不要使用前缀来命名数据库对象 - 除了视图和表(你通常应该想要无法区分)所有对象类型都可以通过它们的用法清楚地看出 - 从任何特定查询中的名称的位置总是清楚的是该名称是指存储过程,(表格视图)还是列等。
答案 1 :(得分:0)
CREATE VIEW HierarchyExpanded AS
BEGIN
SELECT LVL1.ID AS [LVL1ID]
,LVL1.[Type] AS [LVL1Type]
,LVL2.ID AS [LVL2ID]
,LVL2.[Type] AS [LVL2Type]
,LVL3.ID AS [LVL3ID]
,LVL3.[Type] AS [LVL3Type]
,LVL4.ID AS [LVL4ID]
,LVL4.[Type] AS [LVL4Type]
FROM tblProjectItem LVL1
INNER JOIN tblProjectItem LVL2
ON LVL2.fk_Parent = LVL1.ID
INNER JOIN tblProjectItem LVL3
ON LVL3.fk_Parent = LVL2.ID
INNER JOIN tblProjectItem LVL4
ON LVL4.fk_Parent = LVL3.ID
END
CREATE PROC [dbo].[spProjectItemGetTopParentId]
@ID INT
AS
BEGIN
DECLARE @parentId INT
SELECT [LVL1ID]
FROM HierarchyExpanded
WHERE ([LVL1ID] =@ID
OR [LVL2ID] =@ID
OR [LVL3ID] =@ID
OR [LVL4ID] =@ID)
AND [LVL1Type] = 32
END