我可以递归查询XML吗?

时间:2012-09-26 14:32:55

标签: sql sql-server xml recursion

这看起来有点傻,但我想一次尝试解决这个问题。

我在SQL数据库中有一个表链接回自身。它具有组织ID和父组织ID。顶级组织的父ID为0,并且不同级别的每个组织都具有其上一个组织的父组织。组织的级别曾经由名为org Level的表中的另一个字段确定。但是,现在水平取决于组织树的下降距离。这样,如果一个组织的父母有另一个父母,那么第一个组织将处于3级,它的父级位于2级,而它的祖父母级别为1级。

我理解我希望我的SQL如何工作,但问题是创建一个通用的SQL语句,它会返回组织及其级别。我决定尝试使用XML来做到这一点,但这可能不是最好的主意。假设我有一个这样的组织结构。

-Top Org 1
--Second Org 1
--Second Org 2
-Top Org 2
--Second Org 3
--Second Org 4
-Top Org 3
--Second Org 5
--Second Org 6

完成后,我想查询如下所示的XML:

<Organizations>
  <Lvl1 OrgID="1" Name="Top Level 1" Index="1">
    <Lvl2 OrgID="5" Name="Second Level 1" Index="1" />
    <Lvl2 OrgID="6" Name="Second Level 2" Index="2" />
  </Lvl1>
  <Lvl1 OrgID="3" Name="Top Level 2" Index="2">
    <Lvl2 OrgID="7" Name="Second Level 3" Index="1" />
    <Lvl2 OrgID="8" Name="Second Level 4" Index="2" />
  </Lvl1>
  <Lvl1 OrgID="4" Name="Top Level 3" Index="3">
    <Lvl2 OrgID="9" Name="Second Level 5" Index="1" />
    <Lvl2 OrgID="10" Name="Second Level 6" Index="2" />
  </Lvl1>
</Organizations>

如果我知道要查询多少级别,我已经弄清楚我想要如何正常执行此操作。如果我想查询第一级和第二级,我会这样做:

SELECT
    Lvl1.Org_ID [@OrgID]
    ,Lvl1.Org_Name [@Name]
    ,Lvl1.Org_SortID [@Index]
    ,(
        SELECT
            Lvl2.Org_ID [@OrgID]
            ,Lvl2.Org_Name [@Name]
            ,Lvl2.Org_SortID [@Index]
        FROM Organizations Lvl2
        WHERE Lvl2.Org_ParentID = Lvl1.Org_ID
        GROUP BY Lvl2.Org_ID, Lvl2.Org_Name, Lvl2.Org_SortID
        ORDER BY Lvl2.Org_SortID
        FOR XML PATH('Lvl2'), TYPE
    )
FROM Organizations Lvl1
INNER JOIN Organizations Child1 ON Lvl1.Org_ID = Child1.Org_ParentID
WHERE Lvl1.Org_ParentID = 0
GROUP BY Lvl1.Org_ID, Lvl1.Org_Name, Lvl1.Org_SortID
ORDER BY Lvl1.Org_SortID
FOR XML PATH('Lvl1'), ROOT('Organizations')

但是让我假装我不知道我会有多少级别。我可能只有两个级别,我可能有15个级别。并非每个组织都可以拥有相同数量的级别。我想知道的是,如果有一种方法可以递归地查看每个记录,并确定它是否有任何子记录。如果是这样,为这些孩子创建新的XML标签并向下钻取一个级别,然后检查每个孩子并查看他们是否有孩子。等。

也许没有一种好的方法可以做到这一点,或许多是一个巨大的内存和时间汇,使SQL做这样的事情。但如果不是,请告诉我这是可能的并向我展示一个例子。谢谢!

1 个答案:

答案 0 :(得分:2)

我最近有类似的问题,我通过使用递归函数解决了问题(即它自己调用)。

我没有做过任何测试,但这样的事情应该有效:

CREATE FUNCTION dbo.GetChildOrganisations (@ParentID INT)
RETURNS XML
AS
BEGIN
    RETURN 
    (   SELECT  Org_ID [@OrgID],
                Org_Name [@Name],
                Org_SortID [@Index],
                dbo.GetChildOrganisations(Org_ID) [ChildOrganisations] 
        FROM    Organizations 
        WHERE   Org_ParentID = @ParentID
        FOR XML PATH('Orgainisations')
    )
END
相关问题