SQL Server:对分层数据进行分组

时间:2016-04-19 17:33:00

标签: sql sql-server hierarchy

我有一份文件表 - 见下文的定义

在此表中,我们有一个根文档,其OriginalDocID为空

每次修订时,都会添加一个新条目,其中父母documentIDOriginalDocID

我要做的是能够对OriginalDocID为null的原始文档进行分组/分区

每个文档可以从一个原点进行多次修订。

意思是我们可以拥有

Doc Id 1 -> 2 -> 3
       2 -> 8 -> 9
       1 -> 4 -> 7
       5 -> 10

所以我希望看到的是带有根文档的所有行。附加

我希望这是有道理的。对于我的生活,我无法绕过足够的询问。

CREATE TABLE [dbo].[Document](
    [DocumentID] [int] IDENTITY(1,1) NOT NULL,
    [DocumentName] [varchar](max) NOT NULL,
    [ContentType] [varchar](50) NULL,
    [DocumentText] [varchar](max) NULL,
    [DateCreated] [datetime] NULL,
    [DocumentTypeId] [int] NULL,
    [Note] [varchar](8000) NULL,
    [RefID] [int] NULL,
    [Version] [int] NULL,
    [Active] [bit] NULL,
    [OriginalDocID] [int] NULL
)

1 个答案:

答案 0 :(得分:3)

您需要使用递归CTE来执行此操作。这是一个引用回自身的查询,因此它可以遍历层次结构并收集信息,因为它可以向下(或向上)该层次结构的级别。

在您的情况下,例如:

WITH RECURSIVE docCTE AS
(
    /* Recursive Seed */
    SELECT
        cast(null as int) as parentdoc
        documentID,
        0 as depth,
        documentid as originalDocument,
        CAST(null as varchar(100) as docpath
    FROM
        dbo.document
    Where originalDocID IS NULL

    UNION ALL

    /* Recursive Term */
    SELECT
        docCTE.DocumentID as parentdoc,
        document.documentID,
        depth + 1 as depth,
        docCTE.originalDocument,
        docCTE.Path + '>' + document.documentID
    FROM
        docCTE
        INNER JOIN dbo.document on doccte.document = document.originalDocID
    WHERE
        depth <= 15 /*Keep it from cycling in case of bad hierarchy*/

)

SELECT * FROM docCTE;

递归CTE由两部分组成。

  1. 递归种子,这是我们用来查询的内容。这是originalDocID为null的所有文档记录。

  2. 递归术语,我们将表连接回建立父/子关系的递归CTE。

  3. 在您的情况下,我们将递归种子中的文档作为originalDoc捕获,以便我们可以在开始遍历文档层次结构时将其记录下来。

    当你开始时,这些可能有点压倒性,但是在你写了几次之后,这是第二天性(当你遇到更多这种类型的时候,你会发现它真的非常有用数据)。