【问题标题】:TSQL Recursive CTE - get child record id up to a certain pointTSQL Recursive CTE - 获取子记录ID到某个点
【发布时间】:2016-08-09 19:37:36
【问题描述】:

我有以下记录集,我正在尝试从给定的父 ID 获取链接 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 .

提前感谢任何帮助或指导

【问题讨论】:

  • 你想要的最终输出是什么?
  • 很难理解您要达到的目标...为什么不能简单地使用SELECT * FROM @TableVals WHERE [NewId] = '00897' 为什么不想要00903 WHEN ID 是00897 ?跨度>
  • 我也不确定这里到底发生了什么,但我有一个评论。您可以将链接字段设为空并将值移动到存档字段 (UsedToBeLinkedTo),而不是尝试合并 IsUnlinked 字段。我只是建议这是因为层次结构的标准 cte 有据可查。
  • 是的,我认为这将不得不导致架构更改。或 CTE 以外的替代方案。谢谢

标签: sql sql-server sql-server-2008 tsql ssms


【解决方案1】:

我相信您的代码很好,但由于您的数据集,您对预期结果的期望是错误的。

这条记录

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

00903 链接到00897,然后将00903 链接到00900, 00901, and 00902,所以当你使用递归时,你会得到适当的结果.....

【讨论】:

  • 是的,我只需要盯着它看,玩几分钟的查询,信息过载必须筛选......
  • 嗯,我刚刚将您的 not exists 移到 cte 中,但没有得到您想要的结果,但我还是有点困惑,因为您还没有指定如何限制链接日期。 .....你能发布你的新代码和解释吗
【解决方案2】:

这样的东西能行吗?

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 )

【讨论】:

  • 否,因为如果不存在取消链接 00903 的记录,则不会返回 ID 0090000902。它可能需要更改架构。使其更易于使用。
  • 他们不会做什么?.. 如果 NewId = 00903 它会返回它们.. 你是说表中没有记录吗?
  • 这适用于当前数据集。但是当我删除记录 WHERE IsUnlink = 1 - 即 00903 仍然链接时 - 我仍然只返回四条记录。在这里,删除了取消链接记录后,我希望看到所有六个都返回。我认为这并不容易。
猜你喜欢
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
相关资源
最近更新 更多