我有一张桌子Element (id int, type nvarchar)
。每个元素可能有一个或多个父元素,由某些关系定义,具体取决于它的类型。这些父母可能有自己的一组父母,这取决于它的自己的类型。
我想要查询的是另一个元素的祖先(父母,父母,...)的所有Element
条记录。
我已经定义了一个函数,给定id
和type
,返回该元素的父级列表。
CREATE FUNCTION [dbo].[GetParentElementIds] (
@ElementId int,
@ElementType nvarchar(50)
)
RETURNS @ParentElementIds TABLE (id int primary key not null, type nvarchar(50) not null)
AS
BEGIN
IF @ElementType = 'channel' BEGIN
DECLARE @PortId int
-- Some logic to map the @ElementId to a related @PortId
INSERT INTO @ParentElementIds VALUES (@PortId, 'port')
END ELSE IF @ElementType = 'port' BEGIN
DECLARE @CardId int
-- Some logic to map the @ElementId to a related @CardId
INSERT INTO @ParentElementIds VALUES (@CardId, 'card')
END
RETURN
END
......而且这项工作本身就是如此。接下来,我想创建一个递归CTE,在其结果集上重复调用GetParentElementIds()
,以获取祖先列表。不幸的是,这是我的主计划开始动摇的地方,我对确切的查询语法不太确定:
WITH all_ancestor_elements (element_id, type)
AS (
SELECT id AS element_id, type FROM Element WHERE id IN (SELECT id FROM dbo.GetParentElementIds(5, 'channel'))
UNION ALL
SELECT dbo.GetParentElementIds(e.id, e.type) FROM Element e WHERE e.id IN (SELECT element_id FROM all_ancestor_elements)
)
SELECT * FROM all_ancestor_elements;
我得到的错误是:
Msg 465,Level 16,State 1,Line 5 子查询中不允许递归引用
任何帮助都会受到影响。我不会被迫采用目前的方法,并乐意欢迎任何更好的方法;这只是我选择的当时看起来最好的路径!
谢谢, 马特
答案 0 :(得分:1)
问题是你如何在这里调用你的表值函数:
SELECT dbo.GetParentElementIds(e.id, e.type) FROM Element e
你需要使用类似的东西:
SELECT g.id, g.type
FROM Element e
CROSS APPLY dbo.GetParentElementIds(e.id, e.type) g
我不是100%确定你的确切逻辑,但我猜你的最终查询最终会像:
WITH all_ancestor_elements (element_id, type)
AS (
SELECT id AS element_id, type
FROM Element
WHERE id IN (SELECT id FROM dbo.GetParentElementIds(5, 'channel'))
UNION ALL
SELECT g.id, g.type
FROM all_ancestor_elements e
CROSS APPLY dbo.GetDirectAffectorElementIds(e.element_id, e.type) g
)
SELECT *
FROM all_ancestor_elements;