0

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

我在 SQL 数据库中有一个链接回自身的表。它有一个组织 ID 和一个父组织 ID。顶级组织的父 ID 为 0,不同级别的每个组织都有其上一个组织的父组织。组织的级别过去由表中称为组织级别的另一个字段确定。但是,现在级别取决于组织在树下的位置。这样,如果一个组织的父级有另一个父级,则第一个组织将处于第 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 做这样的事情需要大量的内存和时间。但如果不是,请告诉我这是可能的,并给我举个例子。谢谢!

4

1 回答 1

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
于 2012-09-26T16:09:06.723 回答