我有两个带有 hierarchyid 字段的表,其中一个是一个临时表,其中包含需要合并到另一个中的新数据(即需要添加到主树的一组节点,其中一些可能已经是那里)。
除了定义树结构(父/子关系)的 hierarchyid 列。每个表都有一个单独的列,其中包含唯一标识每个节点的节点标识符。也就是说,判断临时表中的节点是否已经在主表中的方法是通过节点 ID,而不是通过 hierarchyid 列。
当务之急,需要执行的处理看起来像这样:
For each row, RS, in the staging table:
If there is not already a row with the same Id as RS in the main table:
Find the parent, PS, of the staging row
Find the row, PM, in the main table that has the same node ID as PS
Create a new child, RM of row PM
Set PM's ID equal to the ID of RS
重要的是,这种方法只有在暂存表中的树以广度优先顺序排序/遍历时才有效——这样当遇到 RS 时,可以保证其父 PS 在主表中已经有相应的行。
到目前为止,我可以看到在 SQL Server 中实现此目的的唯一方法是在暂存表(已经排序)上使用游标,并为每一行调用一个存储过程,该过程基本上完全按照上述方式完成,并带有 SELECT MAX() 查找已经作为 PM 的子级存在的最高层次结构 ID,以便可以唯一地添加子级。
不过,这是一种非常低效的方法,而且对于我的目的来说太慢了。有没有更好的办法?
作为背景,这是我正在做的一种可行性检查。我需要弄清楚我是否可以在 SQL Server 中快速执行此操作。如果事实证明我不能,我将不得不在数据库之外以另一种方式进行。树的合并是问题域所固有的(实际上,在某种意义上是),因此以不同的方式构造数据或采取更广泛的观点并试图以某种方式完全避免执行此操作不是一种选择。
更新
根据要求,这是一个具体的例子。
表“staging”和“main”都有相同的两列:
hierarchy_id of type hierarchyid
node_id of type bigint
初始内容
主要的:
hierarchy_id node_id
/1/ 1
/1/1/ 2
/1/2/ 3
/1/3/ 4
分期:
hierarchy_id node_id
/1/ 1
/1/1/ 3
/1/2/ 5
/1/1/1/ 6
所需内容
主要的:
hierarchy_id node_id
/1/ 1
/1/1/ 2
/1/2/ 3
/1/3/ 4
/1/4/ 5
/1/2/1/ 6
请注意,暂存表中具有hierarchy_id /1/1/ 的节点对应于目标表中具有hiearchy_id /1/2/ 的节点(这就是node_id 很重要的原因——不能只复制hierarchy_id 值)。另请注意,将 node_id 为 6 的新节点添加为正确父节点的子节点,即 node_id 为 3 的节点,这就是 hierarchy_id 很重要的原因 - 它定义了任何新节点的树结构(父/子关系)。任何解决方案都需要考虑这两个方面。