【发布时间】:2015-07-23 09:43:15
【问题描述】:
我们在 SQL Server 2012 数据库中有一个存储树状结构的表。为了我的问题而简化,它具有以下格式:
Id int identity,
ParentId int,
GroupId int
表的每条记录代表一个由 Id 标识的对象。一个对象在同一个表中可能有也可能没有父级,例如 object.ParentId = parentObject.Id。根对象有 ParentId = NULL。有多个根对象,因此该表实际上存储了多个树。 重要的是树的深度不是固定的,即理论上一个对象可以有任意数量的祖先代。 GroupId 是根对象的属性;理论上,根对象的所有子对象都不必具有 GroupId NULL;可以假设任何子对象都具有与其根对象相同的 GroupId 值。
具有两个根(一个祖父母和一个父)、一个非根父/子和 4 个子根的示例表:
Id ParentId GroupId
----------------------------------------------------------
1 NULL 200 root grandparent
2 1 NULL non-root parent/child
3 2 NULL child
4 2 NULL child
5 NULL 300 root parent
6 5 NULL child
7 5 NULL child
该表未标准化,即没有单独的 {root_object : group} 表。但是,我认为规范化表格不会有助于解决问题。
现在问题。我们需要设置合并复制从上面的表(主表)到另一个DB中相同格式的表。我们只需要复制主表中具有某个固定 GroupId 值的行,例如在上面的示例中为 200。如果我们确保根对象的所有后代对象中的 GroupId 在表中与根对象本身具有相同的值,那将是微不足道的。表格如下所示:
Id ParentId GroupId
----------------------------------------------------------
1 NULL 200 root grandparent
2 1 200 non-root parent/child
3 2 200 child
4 2 200 child
5 NULL 300 root parent
6 5 300 child
7 5 300 child
过滤器看起来像这样:
WHERE GroupId = 200
但是出于性能考虑,我们希望尽可能避免为后代对象填充 GroupId,因为从上面必须清楚,GroupId通过存储过程或 UDF 可以很容易地推断出后代对象(只需要上树直到 ParentId = NULL)。 问题是,我不知道如何在合并复制过滤器中实现这一点:它只允许 WHERE 条件和连接。一般来说,我对合并复制的连接不太幸运,但这里我们有更复杂的算法,因为每个对象的树级别数可能不同。 并且合并复制不允许使用 UDF……
【问题讨论】:
标签: sql sql-server filter merge-replication