如何拆分此现有数据库表以减少冗余

时间:2015-04-14 00:31:34

标签: sql database relational

我有一张太大而无法处理的现有表格。我试图将它分成两个表,但仍然不满意。

这是表的样子,(package_id是包表的外键),

    child_company title_category title_level revision start_date package_id
 ---------------------------------------------------------------------------
    c1             manager         senior      0       2015/1/1    120
    c1             manager         senior      1       2014/7/1    119
    c1             architect       senior      0       2014/7/1    70

    c2             architect       junior      0       2015/3/1    70

    c3             manager         senior      0       2015/1/1    120
    c3             manager         senior      1       2014/7/1    119

    c4             manager         senior      0       2015/2/1    122
    c4             manager         senior      1       2014/2/1    102
    c4             manager         senior      2       2013/7/1    101

    c5             manager         senior      0       2015/1/1    120
    c5             manager         senior      1       2014/7/1    119

这张表的问题在于,许多子公司都有类似的薪资信息和历史。 (历史记录由revision表示。revision = 0表示当前的工资信息。)。例如,c1c3c5对高级管理人员的报酬相同。

拆分此表以减少冗余的最佳方法是什么?

我试图将其拆分为

    child_company title_category title_level group_id
 --------------------------------------------------------
    c1             manager         senior      0 
    c1             architect       senior      1
    c2             architect       junior      2
    c3             manager         senior      0
    c4             manager         senior      3
    c5             manager         senior      0

并且

id     group_id start_date package_id
1      0        2015/1/1    120
2      0        2014/7/1    119
3      1        2014/7/1    70
4      2        2015/3/1    70
5      3        2015/2/1    122
6      3        2014/2/1    102
7      3        2013/7/1    101

更好的解决方案?感谢

1 个答案:

答案 0 :(得分:0)

这是我八年前使用我称之为Version Normal Form(vnf)开发的模型。第一个表是主实体表,其中包含静态的,不变的数据,或者可能会更改但您没有跟踪更改的数据。第二个表包含每个版本,每当基础数据发生变化时都会输入新版本。

create table Static(
    ID    int not null primary key auto increment,
    Company  varchar( 8 ) not null,
    Title varchar( 32 ) not null,
    Level varchar( 16 ) not null,
    Created date not null default SysDate
);
create table Versions(
    ID    int not null references Static( ID ),
    Effective date default SysDate,
    PackageID int references Package( ID ),
    constraint PK_Versions primary key( ID, Effective )
};

表示您显示的数据(使用最旧的start_date来模拟合理的创建日期):

Static
ID   Company Title     Level   Created
 1   C1      Manager   Senior  2014/7/1
 2   C1      Architect Senior  2014/7/1
 3   C2      Architect Junior  2015/3/1
 4   C3      Manager   Senior  2014/7/1
 5   C4      Manager   Senior  2013/7/1
 6   C5      Manager   Senior  2014/7/1

Versions
ID   Effective PackageID
 1   2015/1/1        120
 1   2014/7/1        119
 2   2014/7/1         70
 3   2015/3/1         70
 4   2015/1/1        120
 4   2014/7/1        119
 5   2015/2/1        122
 5   2014/2/1        102
 5   2013/7/1        101
 6   2015/1/1        120
 6   2014/7/1        119

使应用程序开发人员易于使用的关键是视图。首先,视图仅显示当前数据。当前版本是具有最新生效日期的版本:

create view Current as
    select  s.Company as child_company, s.Title as title_category,
            s.Level as title_level, v.Effective as start_date
            v.PackageID as package_id
    from    Static   s
    join    Versions v
        on  v.ID   = s.ID
        and v.Effective =(
            select  Max( Effective )
            from    Versions
            where   ID = v.ID );

另一个视图是历史视图。它显示了过去和现在的所有版本:

create view History as
    select  s.Company as child_company, s.Title as title_category,
            s.Level as title_level, v.Effective as start_date
            v.PackageID as package_id
    from    Static   s
    join    Versions v
        on  v.ID   = s.ID;

注意它是相同的查询,只是没有最后四行。

“历史记录”视图的instead of触发器不执行任何操作,因此将其呈现为只读。 Current视图具有管理底层结构的instead of个触发器。特别是,update触发器执行新版本的插入而不是实际更新。

这看起来有点复杂,但其中的好处是

  • 它使用了规范化,开发人员已经知道了。
  • 版本相互独立 - 也就是说,插入新版本时,不得以任何方式修改其他版本。
  • 如果计划在将来进行更改,您可以继续输入有效设置为该未来日期的更改。当前版本保持最新,直到该时间到达,计划版本成为新的当前版本。
  • 需要进行一些小修改才能获得对数据的完整双时间访问。它看起来不像你需要但你永远不知道。

注意:要使用“future version”功能,只需将and Effective <= Sysdate添加到Current视图的子查询中。