0

在我正在处理的 web 应用程序中,有一张桌子可以容纳,所谓的ProjectItems. 问题是不同类型的项目项驻留在同一个表中;你可以创建一个项目、一个问题、一个想法和一个反应。对于按位列,类型在[Type]列中设置。fk_Parent并且每个项目项在同一个表中都可以有一个父项(由名为 的列定义)。

层次结构是这样的:

Project(32) > Question(1) > Idea(2) > Reaction(4)

(我对数据库设置没有任何影响。)

我现在正在创建一个存储过程,用于获取 ID 作为参数传递的任何项目的根项目项目(项目类型),但到目前为止我所得到的感觉有点笨拙:

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
4

2 回答 2

1

是的,递归 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

作为旁注,我建议不要使用前缀来命名您的数据库对象 - 除了视图和表(您通常应该无法区分)所有对象类型都可以通过它们的用法清楚地辨别 - 它总是很清楚名称在任何特定查询中的位置,无论该名称是指存储过程、(表|视图)还是列等。

于 2013-11-08T15:45:54.097 回答
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
于 2013-11-07T09:09:40.080 回答