Sql 存储和查询实体沿袭

Sql 存储和查询实体沿袭,sql,sql-server,database,data-structures,Sql,Sql Server,Database,Data Structures,假设有一个合同数据表,恰当地命名为dbo.Contracts。合同到期后,将在表中创建新行。我需要跟踪旧合同和新合同的合同号。例如,合同号123456今天到期。应用程序今天创建续订合同(合同号888888)。属于合同编号8888的行的字段dbo.Contracts.PreviousContractID更新为123456 没关系。然而,多年以后,最终会有一系列合同。123456续签为合同888888,合同续签为999999等 ------------------------------------

假设有一个合同数据表,恰当地命名为dbo.Contracts。合同到期后,将在表中创建新行。我需要跟踪旧合同和新合同的合同号。例如,合同号123456今天到期。应用程序今天创建续订合同(合同号888888)。属于合同编号8888的行的字段dbo.Contracts.PreviousContractID更新为123456

没关系。然而,多年以后,最终会有一系列合同。123456续签为合同888888,合同续签为999999等

----------------------------------------------------------------
Table dbo.Contracts
----------------------------------------------------------------
ContractID | Lots of other fields | PreviousContractID
----------------------------------------------------------------
123456     |                      | NULL
----------------------------------------------------------------
888888     |                      | 123456
----------------------------------------------------------------
999999     |                      | 888888
我如何写一个查询,说“给定合同号9999999,查询链中的所有合同。”我不知道从哪里开始。我甚至不确定添加一个字段dbo.Contracts.PreviousContractID是否是正确的设计

所需的查询将显示“对于合同号999999,获取“链”中的所有合同”:


我不是在寻找一个完整的代码解决方案,而是在设计中朝着正确的方向前进。这感觉就像是一个“递归自连接”,如果有这样的事情,我会迷路的。

一个简单的递归CTE应该可以做到这一点

Declare @YourTable Table ([ContractID] varchar(50),[PreviousContractID] varchar(50))
Insert Into @YourTable Values
 (123456,NULL)
,(888888,123456)
,(999999,888888)

Declare @ContractID  int = 999999     

;with cteHB as (
      Select [ContractID]
            ,[PreviousContractID]
            ,Lvl=1
      From   @YourTable
      Where  [ContractID]=@ContractID 
      Union  All
      Select R.[ContractID]
            ,R.[PreviousContractID]
            ,P.Lvl+1
      From   @YourTable R
      Join   cteHB P on P.[PreviousContractID] = R.[ContractID])
Select Lvl  
      ,A.[ContractID]
      ,A.[PreviousContractID]
From cteHB A
Order By 1
返回

Lvl ContractID  PreviousContractID
1   999999      888888
2   888888      123456
3   123456      NULL

你应该研究一下。那么,这怎么不是一个复制品呢?…甚至是正确的设计。我也不是。正确的设计取决于你的目标和你试图建立的模型。也许您需要在“扩展”之间形成某种父级关系,这意味着至少有一个其他表和透视图的更改。有时候,你需要尝试不同的方法来处理你的表格,并根据你的数据/目标来验证它们。@ZoharPeled我真诚地没有不尊重的意思。我甚至不知道我重新开放的投票会推翻你的投票。也就是说,你链接到了自上而下,而OP需要自下而上。没问题,我只是想知道。嗯,几乎所有的递归cte问题都是重复的,所以我很惊讶,仅此而已。这应该可以做到。谢谢@硬编码很高兴它有帮助。
Lvl ContractID  PreviousContractID
1   999999      888888
2   888888      123456
3   123456      NULL