Рекурсивный запрос иерархических данных с использованием CTE - PullRequest
1 голос
/ 17 июня 2011

У меня есть две таблицы

CREATE TABLE [dbo].[Folder](
  [FolderID] [int] IDENTITY(1,1) NOT NULL,
  [FolderName] [varchar](50) NOT NULL,
  [ParentFolderID] [int] NULL
)

и

CREATE TABLE [dbo].[FolderSubscription](
  [UserID] [int] NOT NULL,
  [FolderID] [int] NOT NULL,
  [IncludeSubfolders] [bit] NOT NULL
)

Поле [IncludeSubfolders] означает, что если пользователь также подписан на подпапки.

Моя цель - узнать, подписался ли пользователь на определенную папку.

Я попробовал следующий рекурсивный запрос.но не повезло

DECLARE @FolderID INT=2,
        @UserID INT= 1
WITH SubFolderS_CTE (FolderID,ParentFolderID,FolderSubscription)
AS
(
        SELECT 
            Folder.FolderID,
            Folder.ParentFolderID,
            DMSsubscription.IncludeSubfolders
        FROM 
            FolderSubscription
        INNER JOIN 
            Folder
        ON 
            Folder.FolderID = FolderSubscription.FolderID
        WHERE 
            FolderSubscription.FolderID = @FolderID AND FolderSubscription.UserID = @UserID

        UNION ALL
        SELECT
            folder.FolderID,
            folder.ParentFolderID
            ,sub.IncludeSubfolders
        FROM
            FolderSubscription sub
        INNER JOIN
                Folder folder
        ON   folder.FolderID = sub.FolderID
        INNER JOIN
            SubFolderS_CTE
        ON folder.FolderID = SubFolderS_CTE.ParentFolderID
)
SELECT * FROM SubFolderS_CTE

Данные ..

FolderID |  FolderName |  ParentFolderID
----------------------------------------
   1     |     Po      |     NULL       
   2     |   Tigress   |      1         
   3     |    Mantis   |      2         

Подписка ..

 UserID  |   FolderID  |  IncludeChildren
----------------------------------------
   1     |     2       |      1       

Ответы [ 2 ]

1 голос
/ 17 июня 2011

Если вы не можете или не хотите использовать hierarchyid в соответствии с предложением @CResults, вы можете начать с простого CTE's.

DECLARE @IsSubscribedToFolderID INT = 2
DECLARE @UserID INT = 1

/* Test Data */
;WITH Folder (FolderID, FolderName, ParentFolderID) AS (
    SELECT  1, 'Po', NULL
    UNION ALL SELECT 2, 'Tigress', 1
    UNION ALL SELECT 3, 'Mantis', 2
)
, FolderSubscription (UserID, FolderID, IncludeChildren) AS (
    SELECT  1, 2, 1
)
/* Actual Query */
, q AS (
    SELECT  f.FolderID
            , [MasterFolderID] = f.FolderID
    FROM    Folder f
            INNER JOIN FolderSubscription fs ON fs.FolderID = f.FolderID
    WHERE   fs.UserID = @UserID
    UNION ALL
    SELECT  f.FolderID
            , q.MasterFolderID
    FROM    q
            INNER JOIN Folder f ON f.ParentFolderID = q.FolderID
            INNER JOIN FolderSubscription fs ON fs.FolderID = q.MasterFolderID AND fs.IncludeChildren = 1)
SELECT  q.*
FROM    q
        INNER JOIN Folder f ON f.FolderID = q.FolderID
WHERE   q.FolderID = @IsSubscribedToFolderID
.
1 голос
/ 17 июня 2011

Рассмотрите возможность использования типа данных hierarchyid.Это делает такие запросы намного проще.Поиск того, является ли одна папка потомком другой, - это просто предложение where, а не множество рекурсий.

К сожалению, хотя это опция SQL2008 +, которая из ваших тегов может помешать вам использовать ее

...