合并

时间:2015-08-07 11:26:26

标签: design-patterns database-design merge database-schema

我们有一个相当陈旧的数据库,其中包含大量个人以及他们已完成的一些成就。历史上几乎没有什么可以阻止重复的个人数据,所以我们的数据非常肮脏。可以找到大量简化的版本here

我们现在正在重新设计架构和用户界面。我们将为用户提供将他们的个人合并在一起的工具。在提供的例子中,戴夫和大卫显然是同一个人,并且总共取得了4项成就。

鉴于用户犯了错误并且涉及的表比示例中多得多,我正在寻找一种便于合并数据的架构设计,特别是如果(当!)用户不可避免地犯了错误。

某种类型的链接列表似乎是一种解决方案,但对于此用例并不是完全有效的。还有其他概念可能会适应这种情况吗?任何可能适合的特定设计模式?

编辑:由于今天SQLFiddle相当不稳定,所以在sqlfiddle上创建/插入/选择sql:

CREATE TABLE individual
    (`individual_id` int, `forename` varchar(50), `surname` varchar(50))
;

CREATE TABLE achievement
    (`achievement_id` int, `name` varchar(50), `description` varchar(50))
;

CREATE TABLE individual_achievement
    (`individual_id` int,`achievement_id` int)
;

INSERT INTO individual
    (`individual_id`, `forename`, `surname`)
VALUES
    (1, 'Dave', 'Deane'),
    (2, 'David', 'Deane')
;

INSERT INTO achievement
    (`achievement_id`, `name`, `description`)
VALUES
    (1, 'unit_1', 'Unit 1'),
    (2, 'unit_2', 'Unit 2'),
    (3, 'unit_3', 'Unit 3'),
    (4, 'unit_4', 'Unit 4')
;

INSERT INTO individual_achievement
    (`individual_id`,`achievement_id`)
VALUES
    (1, 1),
    (1, 3),
    (2, 2),
    (2, 4)
;

select * from individual i
join individual_achievement ai using (individual_id)
join achievement a using (achievement_id)

编辑2:刚刚找到这个very similar question,希望在4年后也可能有其他解决方案。

1 个答案:

答案 0 :(得分:4)

这是你可以使用的一种策略。

首先,创建一个新表,现在将其称为“Individual_v2”,其列与原始表Individual完全相同。 (理想情况下,您最终将使用此表替换Individual;实际上,人们可能仍然会将数据输入Individual,并且您必须通过移动或合并到Individual_v2来“清理”数据。)配置此表以及指向Achievement的链接。 (现在,我假设成就很干净。)

然后,创建一个“映射”表,如下所示:

IndividualMapping

OldIndividual_Id
NewIndividual_Id
CreatedAt
CreatedBy
ApprovedAt  --  Nullable!
ApprovedBy  --  Nullable!

“已创建”列用于确定创建映射的时间和人员(或具体内容)。

“已批准”列用于确定数据是否已迁移到新表。

对于每个“旧”项目,您可以确定它在“新”表中的映射位置;如果它映射到没有现有项目,请在新表格中为其创建一个项目。

然后,在映射表中添加一个条目。如果创建了新项目,请将其标记为已批准;如果信心很高,请将其标记为已批准;否则,让它“未经批准”并等待审查。在适当的时候,审阅者将查看事物并批准映射,将映射更改为其他现有新项目,或创建另一个新项目并映射到该项目。

完成后,对新表进行“真实”工作。旧表和映射表可用于标识新数据的来源,并在必要时撤消/更改映射。

这里有很多未解决的实施和支持问题,总的来说它看起来很尴尬。长期来看,一旦你解决了重复数据的问题,就可以删除旧的(和映射)表,但在此之前你会有一个繁琐的系统。

<强>附加物

我在这里谈论事情,而不是进行详尽的分析。我认为你正在描述的系统将是繁琐的,在概念上很复杂,即使表格相对简单,最终的细节超出了SO问题的范围。太多,很大程度上取决于系统的总体目标和目标及其重新设计。我将在这里做一些假设:

  • “现有”系统将保持原位

  • 如此输入的个人(及其奖励)必须一如既往地提供。

  • 将继续输入重复项;如果,何时以及在可行的情况下,它们将与现有条目“合并”

通过这种方式,系统将按如下方式工作:

  • Individuals_v2和Achievement之间有一个单独的关系表(Individual_Achievement_v2现在,虽然必须有一个更好的名字)。

  • “v2”表中的数据正确,良好,正确。 “v1”表是登台,历史记录,日志数据。

  • 准备初始版本,其中v1表中的所有条目都在v2表中配置。如果在此步骤中可以合并行,那就更好了。所有内容都会记录在“地图”表中,以便在必要时可以干净利落地重做。

  • 从此版本开始,新数据将输入v1表格,同时/立即输入v2表格。如果可以映射到现有项,请执行此操作,否则在v2表中创建新条目。始终在“地图”表中记录活动。

  • 展望未来,所有“实时”查询都会点击v2表。 v1表(再次)是历史,日志,审计跟踪。一旦填充,它们永远不会被修改,而v2表(包括映射表)可以和将来。

  • 根据业务确定,对数据进行定期审核/检查,查找并修复随时间推移出现的重复条目,以及“无效重复”(不正确的映射)。这是在执行回滚/重做工作时,在映射和v1表中进行跟踪。

您可能需要一些额外的记录表来跟踪“通过xx / xx / xxxx输入的所有数据是否有效,从那时起输入的数据必须经过审核”等内容。我确信还会出现其他问题和微妙之处 - 他们总是这样做......