【发布时间】:2011-10-26 20:42:48
【问题描述】:
我有两个带有 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 很重要 - 它定义了任何新节点的树结构(父/子关系)。任何解决方案都需要考虑这两个方面。
【问题讨论】:
-
有效的第一步是删除目标表中已经存在相同节点 ID 的所有行吗?似乎这样可以消除在合并过程中进行重复检查的需要
-
@OMG Ponies,没有子表和父表。有两个表,每个表都有一个 hierarchyid 列 (msdn.microsoft.com/en-us/library/bb677290.aspx)。节点 ID 建立了两个表中节点的等价性,但是在目标表中尚不存在节点的情况下,仅复制其节点 ID 是不够的 - 它还需要添加到目标表中的适当位置由目标表的 hierarchyid 列定义的层次结构。
-
顺便说一下,我对不使用hierarchyid 的解决方案持开放态度。然而,我的理解是,在没有它们的情况下处理任意深度的树需要公共表表达式,这在语法上看起来很可怕,而且我读过的资料表明它们比层次结构要慢。
-
@Neil N,我可以从源表中删除此类记录,尽管这可能会使我以后要做的一些事情变得复杂。不过,重复检查并不是真正的问题——如果我能用 MERGE 语句实现这一点,那就太好了。
-
我认为如果您给我们一个示例表结构和预期结果会有所帮助。我很难理解为什么你不能用一个简单的
MERGE语句来做到这一点;你不允许改变hierarchyid或者你会有重复的hierarchyid吗?我已经构建了一个自我维护的 hierarchyid/邻接列表混合体,这可能是您正在寻找的,但从问题中很难判断。
标签: sql sql-server sql-server-2008 hierarchical-data hierarchyid