Question

I have a SQL table that stores forum posts. Each record has a ParentID which is the ID of another record. If it is null it means that it is a main forum thread and therefore has no parent record. Every post can have multiple levels of children. I am looking for a function that efficiently recurs through child records to find the one that was created last (each record has a 'Created' field).

I do have a stored procedure that lists records that belong to a specific parent but it is very CPU intensive and it cannot be used when listing main forum threads and showing the date of the last reply.

If it helps, here is the basic structure of the table:

CREATE TABLE [dbo].[ForumThreads](
    [ForumThreadID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [ForumID] [numeric](18, 0) NULL,
    [ParentID] [numeric](18, 0) NULL,
    [PostSubject] [nvarchar](500) NULL,
    [PostBody] [nvarchar](max) NULL,
    [Created] [datetime] NULL,
    [CreatedBy] [numeric](18, 0) NULL
);
Was it helpful?

Solution

I read you answer closely and deleted my first answer because it was wrong. Here is an SQL FIDDLE with a solution that includes a setup and a recursive CTE query that groups all related forums using a "TopLevelForumID" field. This query should be efficient, but depending on your table statistics, you could add an INDEX to improve the response speed.

SQL Fiddle

Added scalar-valued function, which can be called like so:

-- How yo use this Scalar-valued function
--SELECT [ForumThreadID]
--      ,[ForumID]
--      ,[ParentID]
--      ,[PostSubject]
--      ,[PostBody]
--      ,[Created]
--      ,[CreatedBy]
--      ,[dbo].[fn_getLastThread]([ForumID]) AS [LastThread]
--  FROM [dbo].[ForumThreads]

CREATE FUNCTION [dbo].[fn_getLastThread]
(
    @ParentForumID INT
)
RETURNS INT
AS
BEGIN

    DECLARE @Ret INT;

    -- recursive CTE query
    WITH hierarchy AS (

            -- select the parent row
            SELECT  [ForumID],[ParentID],[Created]
            FROM    ForumThreads
            WHERE   [ForumID]=@ParentForumID

            UNION ALL               
            SELECT  A.[ForumID],A.[ParentID],A.[Created]
            FROM    ForumThreads A
            INNER JOIN hierarchy H ON H.[ForumID] = A.[ParentID]
    )
    SELECT      TOP 1 @Ret = [ForumID]
    FROM        hierarchy
    ORDER BY    [Created] DESC
    OPTION      (MAXRECURSION 50); -- specify recursion limit (default is 100 if not specified)

    RETURN @Ret;

END
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top