使用CTE递归查询分层数据

时间:2011-06-17 06:19:11

标签: sql-server sql-server-2005 sql-server-2008 hierarchy common-table-expression

我有两张桌子

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 个答案:

答案 0 :(得分:1)

考虑使用hierarchyid数据类型。它使这样的查询变得更加容易。想看一个文件夹是否是另一个文件夹的后代,那么只是一个where子句而不是很多递归

不幸的是,虽然它只是一个SQL2008 +选项,你的标签可能会阻止你使用它

答案 1 :(得分:1)

如果您不能或不想使用@CResults提议的hierarchyid,以下内容可能会让您开始使用普通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