几分钟前,我问here如何获得递归CTE的父记录。 现在可以使用,但是当我创建一个返回所有父母的表值函数时,我得到了错误的顺序(向后,由PK idData排序)。我不能直接订购,因为我需要CTE提供的逻辑顺序。表值函数的错误订单(保留递归CTE的“订单”)
这给正确的顺序(从明年父母到父母等):
declare @fiData int;
set @fiData=16177344;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
select iddata from PreviousClaims
但下面的函数在向后顺序(由PK订购)将返回所有记录:
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
AS
BEGIN
DECLARE @idData int;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
INSERT INTO @retPreviousClaims
SELECT idData FROM PreviousClaims;
RETURN;
END;
select * from dbo._previousClaimsByFiData(16177344);
更新: 因为大家都认为CTE没有排序()任何“排序“将是完全武断和巧合),我想知道为什么相反似乎是真实的。我向许多父母询问了一个孩子的索赔,而且当我从孩子到父母等等时,CTE中的顺序恰好是合乎逻辑的顺序。这将意味着CTE正在从记录迭代到像记录一样进行记录,下面的select将按照此顺序返回它。但是当我调用TVF时,我得到了主键idData的顺序。
该解决方案很简单。我只需要删除TVF的返回表的父键。因此改变......
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
到...
RETURNS @retPreviousClaims TABLE
(
idData int
)
..它保持正确的 “命令”(相同顺序进行插入CTE的临时结果集)。
UPDATE2: 因为达明提到了“CTE-令”可能在某些情况下发生变化,我将一个新列relationLevel
添加到CTE描述的父记录关系的水平(什么是由对于一个ssas立方体来说,这个方法在一般情况下非常有用) 所以最终的内联TVF(返回所有列)现在是:
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS TABLE AS
RETURN(
WITH PreviousClaims
AS(
SELECT 1 AS relationLevel, child.*
FROM tabData child
WHERE child.idData = @fiData
UNION ALL
SELECT relationLevel+1, child.*
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
SELECT TOP 100 PERCENT * FROM PreviousClaims order by relationLevel
)
这是典型的关系:
select idData,fiData,relationLevel from dbo._previousClaimsByFiData(46600314);
谢谢。
您发布的解决方案*现在可以在当今的服务器,Service Pack和数据库上为您工作。但它不能得到保证。确保结果集排序的唯一方法是在最外面的SELECT语句中指定一个ORDER BY子句。 – 2010-10-15 08:22:12
是的,看起来更好 - 最终输出仍然依赖于实现细节(即INSERT中的“ORDER BY”与检索顺序有任何关系),但至少您有排序列可用于执行ORDER BY这个外层选择,如果你需要的话。 – 2010-10-15 09:14:12
当我将relationLevel定义为主键时它有什么不同吗?那么是否有序保证,并不需要应用于外部选择? – 2010-10-15 10:18:31