2016-08-09 50 views
1

我有下面的记录集,我试图从给定的父ID得到链接ID的列表。TSQL递归CTE - 获取子女记录ID至某一点

DECLARE @TableVals TABLE 
        ([ID] NVARCHAR(5), 
        [NewId] NVARCHAR(5), 
        [LinkDate] DATETIME, 
        [IsUnlink] BIT); 

INSERT INTO @TableVals 
VALUES ('00899', '00897', '01 Jan 2012 13:46:30', 0), 
     ('00900', '00903', '01 Jan 2012 12:05:16', 0), 
     ('00901', '00903', '01 Jan 2012 11:03:13', 1), 
     ('00903', '00897', '01 Jan 2012 11:01:57', 0), 
     ('00902', '00903', '01 Jan 2012 10:44:00', 0), 
     ('00898', '00906', '01 Jan 2012 10:34:36', 1), 
     ('00895', '00897', '01 Jan 2012 10:25:51', 0), 
     ('00893', '00897', '01 Jan 2012 10:25:33', 0), 
     ('00891', '00897', '01 Jan 2012 10:24:48', 0) 

我有这种CTE其返回两个意外的值(0090000902),因为这些被链接到00903这是从解除链接。我试图在LinkDate上进行检查,但我怀疑我没有把它做得很正确。

DECLARE @ID NVARCHAR(5) = '00897' 

;WITH CurrentLinks AS 
(
    SELECT 
     [tv].[ID], [tv].[NewId], [tv].[LinkDate] 
    FROM 
     @TableVals [tv] 
    WHERE 
     [tv].[NewId] = @ID 
     AND [tv].[IsUnlink] != 1 

    UNION ALL 

    SELECT 
     [tv].[ID], [tv].[NewId], [tv].[LinkDate] 
    FROM 
     @TableVals [tv] 
    INNER JOIN 
     CurrentLinks [cl] ON [tv].[NewId] = [cl].[ID] 
         AND [tv].[IsUnlink] != 1 
) 
SELECT 
    [cl].[ID] 
FROM 
    CurrentLinks cl 
WHERE 
    [cl].[id] != @ID 
    AND NOT EXISTS (SELECT 1 
        FROM @TableVals tv 
        WHERE (tv.ID = cl.ID OR tv.NewId = cl.ID) 
         AND tv.LinkDate > cl.LinkDate) 
ORDER BY 
    [cl].[LinkDate] DESC; 

当ID设置为00903我希望0090000902要返回,当ID 00897在传递我希望00899008950089300891

预先感谢任何帮助或方向

+0

你想要的最终输出是什么? – techspider

+0

很难理解你要存档的内容......为什么不能简单地'SELECT * FROM @TableVals WHERE [NewId] ='00897''你为什么不要'00903'当ID是' 00897'? – techspider

+0

我也不确定这里发生了什么,但我有一个评论。您可以清空链接字段并将该值移至归档字段(UsedToBeLinkedTo),而不是尝试合并IsUnlinked字段。我只是建议将此作为层次结构的标准cte文件。 –

回答

1

我相信你的代码是好的,但你的预期结果的期望,是因为你的数据集的错误。

这个纪录

('00903', '00897', '01 Jan 2012 11:01:57', 0), 

链接0090300897然后00903链接00900, 00901, and 00902所以你洁具适当地得到这些作为结果,当你使用递归.....

+0

这就是我在想什么,但我想也许我很困惑... –

+0

是啊我只是不得不盯着它,玩查询几分钟的信息超载必须筛选....... – Matt

+0

嗯,我只是把你的不存在进入cte,并没有得到你想要的结果,但是,我仍然有点困惑,因为你没有指定如何限制链接日期......你可以发布您的新代码和解释 – Matt

0

可能是这样的工作?

SELECT * 
FROM @TableVals tv1 
WHERE [NewId] = @ID 
     AND tv1.IsUnlink <> 1 
     AND NOT EXISTS (SELECT 1 
         FROM @TableVals tv2 
         WHERE tv2.[NewId] = tv1.[ID] 
           AND tv2.IsUnlink = 1) 
+0

不,因为如果解除链接“00903”的记录不存在,则不会返回ID“00900”和“00902”。它可能需要模式更改。使其更容易处理。 – user3047489

+0

他们不会是什么?如果NewId ='00903'它会返回它们..你是说没有记录在表格中吗? – JamieD77

+0

这适用于当前数据集。但是,当我删除记录'WHERE IsUnlink = 1' - 即使'00903'仍然被链接 - 我仍然只有四个记录返回。在这里,删除了取消链接记录,我希望看到所有六个返回。我不认为这很容易做到。 – user3047489