【发布时间】:2010-01-09 00:14:17
【问题描述】:
我有一个描述层次结构的表:
Name MemberName
A B
A C
B D
D E
F G
MemberName 引用同一个表的 Name 列。从这个表中,我可以很容易地查询到 B 和 C 是 A 内的成员,D 是 B 的成员,E 是 D 的成员,G 是 F 的成员。
基于这种结构,很难编写一个查询来显示 D 和 E 也间接地是 A 的成员。D 和 E 也间接地是 B 的成员,等等。所以我需要做的是建立一个显示所有间接成员的新表。因此,对于上面的表格数据,我最终会得到一个包含以下内容的表格:
Name MemberName
A B
A C
A D
A E
B D
B E
D E
F G
我首先将不属于其他记录(顶级)记录的所有记录放入临时表中:
CREATE TABLE #TMP
(
[Name] varchar(20),
[MemberName] varchar(20)
)
DECLARE @iRowsFound INT
INSERT INTO #TMP ([Name],[MemberName])
(SELECT * FROM [HierarchyData] WHERE [Name] NOT IN
(SELECT [MemberName] FROM [HierarchyData]))
SELECT @iRowsFound = @@ROWCOUNT
Name MemberName
A B
A C
F G
然后我的理论是,在 while 循环中,将临时表交叉连接到 heirachy 表,并将交叉连接中的适用记录插入回临时表中,然后执行该 while 循环,直到没有更多适用的记录在交叉连接中插入:
WHILE (@iRowsFound > 0)
BEGIN
INSERT INTO #TMP ([Name],[MemberName])
(
SELECT
[NewName] = ??,
[NewMember] = ??
FROM
[HierarchyData],[#TMP]
WHERE
???
)
SELECT @iRowsFound = @@ROWCOUNT
END
我只是不确定我是否走在正确的轨道上,因为我对交叉连接选择应该是什么样子感到有些困惑。有没有人做过这样的事情(在 sql server 2000 中)?
编辑:我想我可能已经明白了: - 虽然我很确定一定有 更有效的方法...
WHILE (@iRowsFound > 0)
BEGIN
INSERT INTO #TMP ([Name],[MemberName])
(
SELECT
--[#TMP].[Name],
--[#TMP].[MemberName],
[HierarchyData].[Name],
[HierarchyData].[MemberName]
FROM
[#TMP]
JOIN
[HierarchyData] ON [#TMP].[MemberName] = [HierarchyData].[Name]
--WHERE
-- [#TMP].[MemberName] = [HierarchyData].[Name]
AND NOT EXISTS (SELECT * FROM [#TMP] WHERE [#TMP].[Name] = [HierarchyData].[Name] AND [#TMP].[MemberName] = [HierarchyData].[MemberName])
UNION
SELECT
[#TMP].[Name],
--[#TMP].[MemberName],
--[HierarchyData].[Name],
[HierarchyData].[MemberName]
FROM
[#TMP]
JOIN
[HierarchyData] ON [#TMP].[MemberName] = [HierarchyData].[Name]
AND NOT EXISTS (SELECT * FROM [#TMP] WHERE [#TMP].[Name] = [#TMP].[Name] AND [#TMP].[MemberName] = [HierarchyData].[MemberName])
)
SELECT @iRowsFound = @@ROWCOUNT
END
【问题讨论】:
-
@Jeremy:是的,您的代码可以工作,但它比像我的代码那样在临时表中包含循环变量要多做很多工作。由于每个周期必须执行 4 个选择语句,而不仅仅是一个。
标签: sql-server sql-server-2000 hierarchy