【问题标题】:t-sql query to update data recursivelyt-sql 查询递归更新数据
【发布时间】:2019-06-24 01:23:21
【问题描述】:
Max_ID     Second_Max_ID   Cumulative_ID
173          97             ,97
174          173            ,97,173
...          ...            ...

我需要编写一个查询来计算累积 ID。有人可以帮忙吗? 这是一个具有 3 列(Max_ID、Second_Max_ID、Cumulative_ID)的临时表,其中我在表中只有 Max_ID 和 Second_Max_ID 值,我需要为同一个临时表中的每一行计算 Cumulative_ID。

我使用了shnugo提供的查询,修改了如下查询-

DECLARE @mockup TABLE(Max_ID INT,Second_Max_ID INT);
INSERT INTO @mockup VALUES
(173 , 97   )
,(174 , 173  );

WITH recCTE AS
(
    SELECT Max_ID
          ,Second_Max_ID
          ,CAST(Second_Max_ID AS VARCHAR(MAX)) AS Cumulative_ID
    FROM @mockup --WHERE Second_Max_ID IS NULL

    UNION ALL
    SELECT m.Max_ID
          ,m.Second_Max_ID
          ,r.Cumulative_ID+','+ cast(m.Second_Max_ID as varchar(max))
    FROM @mockup m 
    INNER JOIN recCTE r ON r.Max_ID=m.Second_Max_ID
)
SELECT * FROM recCTE;

现在得到的结果像 -

Max_ID  Second_Max_ID   Cumulative_ID
173          97            97
174          173          173
174          173          97,173

如何从上面的结果中删除第二行?

【问题讨论】:

  • 不足以让我关闭为 100% 重复,但您仍然需要 this methodology 或类似的东西。您需要稍微更改连接子句。假设您有一个迭代值的主键
  • 一个Max_ID下面总是只有一个关注者吗?它是1:1 列表、1:n 还是m:n 层次结构?
  • @Shnugo 这是一个动作序列,您可以说出任何记录上第一个动作发生的位置,该 ID 为 97,然后发生第二个动作,该 ID 为 173,然后是第三个,依此类推。现在我需要显示审计,如 97>173>174

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


【解决方案1】:

你可以试试这个:

DECLARE @mockup TABLE(Max_ID INT,Second_Max_ID INT);
INSERT INTO @mockup VALUES
 (97   ,NULL  )
,(173 , 97   )
,(174 , 173  )
,(175 , 174  );

WITH recCTE AS
(
    SELECT Max_ID
          ,Second_Max_ID
          ,CAST(Max_ID AS VARCHAR(MAX)) AS Cumulative_ID
    FROM @mockup WHERE Second_Max_ID IS NULL

    UNION ALL
    SELECT m.Max_ID
          ,m.Second_Max_ID
          ,CONCAT(r.Cumulative_ID,',',m.Max_ID)
    FROM @mockup m 
    INNER JOIN recCTE r ON r.Max_ID=m.Second_Max_ID
)
SELECT * FROM recCTE;

这个想法是一个递归CTE(而不是一个迭代方法)。您从没有 parent 的一行开始(Second_Max_ID IS NULL)。

这会遍历列表(一个隐藏的RBAR)并进行连接动态

您已使用 v2008 和 v2012 进行了标记。如果CONCAT() 不适合您,您可以轻松使用简单的+ 并将所需的转换为varchar

更新

在这个版本中,我将为层次结构深度添加一个计数器:

WITH recCTE AS
(
    SELECT Max_ID
          ,Second_Max_ID
          ,CAST(Max_ID AS VARCHAR(MAX)) AS Cumulative_ID
          ,1 AS HierarchyLevel
    FROM @mockup WHERE Second_Max_ID IS NULL

    UNION ALL
    SELECT m.Max_ID
          ,m.Second_Max_ID
          ,CONCAT(r.Cumulative_ID,',',m.Max_ID)
          ,r.HierarchyLevel+1
    FROM @mockup m 
    INNER JOIN recCTE r ON r.Max_ID=m.Second_Max_ID
)
SELECT * 
FROM recCTE;

你可以使用

  • WHERE 过滤特殊级别
  • TOP 1 与ORDER BY HierachyLevel DESC 相关,以获取最后一个元素(路径最长的元素)。

希望这会有所帮助!

【讨论】:

  • 不使用CTE也能达到同样的效果吗?
  • @Mukund 请问为什么?有(相当丑陋的)方法(例如CURSOR 循环),但这似乎是一种有效的、可内联的(!)方法......
  • @Mukund CTE 几乎是在 SQL Server 中进行递归的最佳方式。
  • @Shnugo 我已经更新了这个问题。你可以检查一次吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 2014-10-27
相关资源
最近更新 更多