In a webapp I'm working on there's a table which holds, so called, ProjectItems
. The thing is that different types of project items reside in the same table; you could create a project, a question, an idea and a reaction. With a bitwise column the type is set in the [Type]
column. And each project item could have a parent (defined by a column named fk_Parent
) in this same table.
The hierarchy is this:
Project
(32) > Question
(1) > Idea
(2) > Reaction
(4)
(I don't have any influence over the DB setup.)
I'm now creating a Stored Procedure for getting the root project item (of type Project) for any item with the ID passed as a parameter, but what I've got so far feels a little clunky:
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
I was wondering if there was any way to do this recursively in SQL? Or some other way to make this a little more neat?
EDIT: This is the SP including the a CTE:
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
Yes, a recursive CTE can find this for you:
;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
As a side note, I'd recommend against using prefixes for naming your database objects - with the exception of views and tables (that you should generally want to be indistinguishable) all object types can be clearly discerned by their usage - it's always clear from the position of a name in any particular query whether that name refers to a stored procedure, a (table|view), or a column, etc.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.