SQL递归 - 父子 - 多个级别

时间:2017-11-21 00:23:19

标签: sql sql-server

我有OutputTemplates - > OutputBookmarks - > OutputNodes - > OutputTemplates - > OutputBookmarks - > OutputNodes ......等

我从一组已知的OutputTemplate中的顶级OutputNodes开始 - > OutputBookmarks

我希望简化下面的查询以获取所有子OutputNodeID和性能。

ALTER PROCEDURE [促销]。[Promote_Outputs_Delete_Output_Nodes_Not_In_Source](@ promotionID UNIQUEIDENTIFIER) 如 BEGIN

WITH
          CTE_OutputOptions
          AS (
          SELECT t.p.value('@OutputOptionID', 'uniqueidentifier') AS OutputOptionID,
                 t.p.value('@TemplateID', 'uniqueidentifier') AS OutputTemplateID
          FROM [Promotion].Promotions AS p
               CROSS APPLY p.OutputsXml.nodes('/Data/dbo.OutputOptions/dbo.OutputOptions') t(p)
          INNER JOIN [dbo].[OutputOptions] oo
          ON oo.OutputOptionID = t.p.value('@OutputOptionID', 'uniqueidentifier')
          WHERE p.PromotionID = @promotionID)

          ,CTE_AllSourceOutputTemplates
          AS (
          SELECT t.p.value('@OutputTemplateID', 'uniqueidentifier') AS OutputTemplateID,
                 t.p.value('@TemplateFileName', 'nvarchar(200)') AS TemplateFileName,
                 t.p.value('@CreatedDate', 'datetime') AS CreatedDate,
                 coalesce(t.p.value('@CreatedByUserID', 'uniqueidentifier'), '00000000-0000-0000-0000-000000000000') AS CreatedByUserID,
                 t.p.value('@DeletedDate', 'datetime') AS DeletedDate,
                 t.p.value('@DeletedByUserID', 'uniqueidentifier') AS DeletedByUserID,
                 t.p.value('@ModifiedByUserID', 'uniqueidentifier') AS ModifiedByUserID,
                 t.p.value('@ModifiedDate', 'datetime') AS ModifiedDate,
                 t.p.value('@IOFileName', 'nvarchar(100)') AS IOFileName
          FROM [Promotion].Promotions AS p
               CROSS APPLY p.OutputsXml.nodes('/Data/Outputs.OutputTemplates/Outputs.OutputTemplates') t(p)
          WHERE p.PromotionID = @promotionID)

          ,CTE_AllSourceBookmarks
          AS (
          SELECT t.p.value('@OutputDocTemplateBookmarkID', 'uniqueidentifier') AS OutputDocTemplateBookmarkID,
                 t.p.value('@OutputTemplateID', 'uniqueidentifier') AS OutputTemplateID,
                 t.p.value('@OutputDocBookmarkTypeID', 'int') AS OutputDocBookmarkTypeID,
                 t.p.value('@Name', 'nvarchar(200)') AS Name,
                 t.p.value('@DisplayOrder', 'int') AS DisplayOrder,
                 t.p.value('@DoPageBreakBefore', 'bit') AS DoPageBreakBefore,
                 t.p.value('@DoPageBreakAfter', 'bit') AS DoPageBreakAfter,
                 t.p.value('@SoftName', 'nvarchar(100)') AS SoftName,
                 t.p.value('@ShowOnOverridePage', 'bit') AS ShowOnOverridePage,
                 t.p.value('@AllowVisibilityOverride', 'bit') AS AllowVisibilityOverride,
                 t.p.value('@AllowForcePageBreak', 'bit') AS AllowForcePageBreak,
                 t.p.value('@ShowOnAllVersions', 'bit') AS ShowOnAllVersions,
                 t.p.value('@DefaultToHidden', 'bit') AS DefaultToHidden
          FROM [Promotion].Promotions AS p
               CROSS APPLY p.OutputsXml.nodes('/Data/Outputs.OutputDocTemplateBookmarks/Outputs.OutputDocTemplateBookmarks') t(p)
          WHERE p.PromotionID = @promotionID)

           ,CTE_AllSourceOutputNodes
          AS (
          SELECT t.p.value('@OutputNodeID', 'uniqueidentifier') AS OutputNodeID,
                 t.p.value('@OutputNodeTypeID', 'int') AS OutputNodeTypeID,
                 t.p.value('@OutputTemplateID', 'uniqueidentifier') AS OutputTemplateID,
                 t.p.value('@OutputTemplateBookmarkID', 'uniqueidentifier') AS OutputDocTemplateBookmarkID,
                 t.p.value('@LinkedToNodeID', 'uniqueidentifier') AS LinkedToNodeID
          FROM [Promotion].Promotions AS p
               CROSS APPLY p.OutputsXml.nodes('/Data/Outputs.OutputNodes/Outputs.OutputNodes') t(p)
          WHERE 
          p.PromotionID = @promotionID)

          ,CTE_TopSourceOutputTemplates
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_OutputOptions opts
          ON opts.OutputTemplateID = aot.OutputTemplateID
          )

          ,CTE_TopSourceBookmarks
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_TopSourceOutputTemplates toptemplates
          ON ab.OutputTemplateID = toptemplates.OutputTemplateID
          )

          ,CTE_TopSourceOutputNodes
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_TopSourceBookmarks topbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  topbookmarks.OutputDocTemplateBookmarkID
          )

          ,CTE_NextOutputTemplates1
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_TopSourceOutputNodes topnodes
          ON topnodes.OutputTemplateID = aot.OutputTemplateID 
          ),

          CTE_NextOutputBookmarks1
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_NextOutputTemplates1 nexttemplates
          ON ab.OutputTemplateID = nexttemplates.OutputTemplateID
          ),

          CTE_NextOutputNodes1
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_NextOutputBookmarks1 nextbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  nextbookmarks.OutputDocTemplateBookmarkID
          )

          --------

           ,CTE_NextOutputTemplates2
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_NextOutputNodes1 nextnodes
          ON nextnodes.OutputTemplateID = aot.OutputTemplateID 
          ),

          CTE_NextOutputBookmarks2
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_NextOutputTemplates2 nexttemplates
          ON ab.OutputTemplateID = nexttemplates.OutputTemplateID
          ),

          CTE_NextOutputNodes2
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_NextOutputBookmarks2 nextbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  nextbookmarks.OutputDocTemplateBookmarkID
          )

          ----------------------

            ,CTE_NextOutputTemplates3
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_NextOutputNodes2 nextnodes
          ON nextnodes.OutputTemplateID = aot.OutputTemplateID 
          ),

          CTE_NextOutputBookmarks3
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_NextOutputTemplates3 nexttemplates
          ON ab.OutputTemplateID = nexttemplates.OutputTemplateID
          ),

          CTE_NextOutputNodes3
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_NextOutputBookmarks3 nextbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  nextbookmarks.OutputDocTemplateBookmarkID
          )

    -------------------------------------

                    ,CTE_NextOutputTemplates4
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_NextOutputNodes3 nextnodes
          ON nextnodes.OutputTemplateID = aot.OutputTemplateID 
          ),

          CTE_NextOutputBookmarks4
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_NextOutputTemplates4 nexttemplates
          ON ab.OutputTemplateID = nexttemplates.OutputTemplateID
          ),

          CTE_NextOutputNodes4
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_NextOutputBookmarks4 nextbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  nextbookmarks.OutputDocTemplateBookmarkID
          )

          ------------------------------

                ,CTE_NextOutputTemplates5
          AS (
          SELECT aot.OutputTemplateID,
                 TemplateFileName,
                 CreatedDate,
                 CreatedByUserID,
                 DeletedDate,
                 DeletedByUserID,
                 ModifiedByUserID,
                 ModifiedDate,
                 IOFileName
          FROM CTE_AllSourceOutputTemplates aot
          INNER JOIN CTE_NextOutputNodes4 nextnodes
          ON nextnodes.OutputTemplateID = aot.OutputTemplateID 
          ),

          CTE_NextOutputBookmarks5
          AS (
          SELECT    OutputDocTemplateBookmarkID,
                ab.OutputTemplateID,
                OutputDocBookmarkTypeID,
                Name,
                DisplayOrder,
                DoPageBreakBefore,
                DoPageBreakAfter,
                SoftName,
                ShowOnOverridePage,
                AllowVisibilityOverride,
                AllowForcePageBreak,
                ShowOnAllVersions,
                DefaultToHidden
          FROM CTE_AllSourceBookmarks ab
          INNER JOIN CTE_NextOutputTemplates5 nexttemplates
          ON ab.OutputTemplateID = nexttemplates.OutputTemplateID
          ),

          CTE_NextOutputNodes5
          AS (
          SELECT  allsourcenodes.OutputNodeID,
                  allsourcenodes.OutputNodeTypeID,
                  allsourcenodes.OutputTemplateID,
                  allsourcenodes.OutputDocTemplateBookmarkID,
                  allsourcenodes.LinkedToNodeID
          FROM CTE_AllSourceOutputNodes allsourcenodes
          INNER JOIN CTE_NextOutputBookmarks5 nextbookmarks
          ON allsourcenodes.OutputDocTemplateBookmarkID =  nextbookmarks.OutputDocTemplateBookmarkID
          )

 select * from CTE_NextOutputNodes5 --where outputtemplateid is not null
 UNION
 SELECT *  from CTE_NextOutputNodes4
 UNION
 SELECT *  from CTE_NextOutputNodes3
 UNION
 SELECT *  from CTE_NextOutputNodes2
 UNION
 SELECT *  from CTE_NextOutputNodes1
 UNION
 SELECT * from CTE_TopSourceOutputNodes

END

- 最终 - 这有效

WITH
CTE_RecursiveTemplateBookmarkNodes AS
(
select t.outputtemplateid, b.outputdoctemplatebookmarkid, n.outputnodeid, n.outputtemplateid as nodetemplateid
from outputs.outputtemplates t
inner join outputs.OutputDocTemplateBookmarks b
on t.outputtemplateid = b.outputtemplateid
inner join outputs.outputnodes n
on b.outputdoctemplatebookmarkid = n.outputtemplatebookmarkid
UNION ALL 
select t.outputtemplateid, b.outputdoctemplatebookmarkid, n.outputnodeid,  n.outputtemplateid as nodetemplateid
from CTE_RecursiveTemplateBookmarkNodes cte
inner join outputs.outputtemplates t
on t.outputtemplateid = cte.nodetemplateid
inner join outputs.outputdoctemplatebookmarks b
on b.OutputTemplateID = t.outputtemplateid
inner join outputs.outputnodes n
on b.outputdoctemplatebookmarkid = n.outputtemplatebookmarkid
)
select distinct * from CTE_RecursiveTemplateBookmarkNodes

1 个答案:

答案 0 :(得分:1)

下面是一个脚本,其中包含示例数据和带有想法的查询,您可以将其应用于您的问题。该脚本可以按原样运行。如果您需要,我可以尝试为您的问题编写确切的查询,但我需要一个用于查询的XML示例。

-- sample data

declare @templates xml = '<root>
    <template id="1"></template>
    <template id="2"></template>
    <template id="3"></template>
    <template id="4"></template>
    <template id="5"></template>
</root>'
declare @bookmarks xml = '<root>
    <bookmark id="1" templateId="1"></bookmark>
    <bookmark id="2" templateId="2"></bookmark>
    <bookmark id="3" templateId="3"></bookmark>
    <bookmark id="4" templateId="4"></bookmark>
    <bookmark id="5" templateId="5"></bookmark>
</root>'
declare @nodes xml = '<root>
    <node id="1" bookmarkId="1" templateId="2"></node>
    <node id="2" bookmarkId="1" templateId="3"></node>
    <node id="3" bookmarkId="2" templateId="4"></node>
    <node id="4" bookmarkId="3" templateId="5"></node>
    <node id="5" bookmarkId="4"></node>
    <node id="6" bookmarkId="5"></node>
</root>'

-- query

;with alltemplates as (
    select id = a.value('@id', 'int') from @templates.nodes('/root/template') a(a)
),allbookmarks as (
    select id = a.value('@id', 'int'), templateId = a.value('@templateId', 'int') from @bookmarks.nodes('/root/bookmark') a(a)
),allnodes as (
    select id = a.value('@id', 'int'), bookmarkId = a.value('@bookmarkId', 'int'), templateId = a.value('@templateId', 'int') from @nodes.nodes('/root/node') a(a)
), cte as (
    select nodeId = allnodes.id, allnodes.templateId from alltemplates
    join allbookmarks on alltemplates.id = allbookmarks.templateId
    join allnodes on allbookmarks.id = allnodes.bookmarkId
    where alltemplates.id = 1 -- join on options instead
    union all
    select allnodes.id, allnodes.templateId from cte
    join allbookmarks on cte.templateId = allbookmarks.templateId
    join allnodes on allbookmarks.id = allnodes.bookmarkId
)

select nodeId from cte