Как разделить эту существующую таблицу базы данных, чтобы уменьшить избыточность

У меня есть таблица, которая слишком велика для обработки. Я пытался разделить его на две таблицы, но все еще не удовлетворен.

Вот как выглядит таблица, (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 указать текущую информацию о зарплате.). Например, c1, c3, а также c5 оба имеют одинаковую плату за старших менеджеров.

Каков наилучший способ разбить эту таблицу, чтобы уменьшить избыточность?

Я пытался разделить это так

    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 ответ

Вот модель, которую я разработал около восьми лет назад, используя то, что я называю версией нормальной формы (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 )
};

Чтобы представить данные, которые вы показываете (используя самую старую дату начала для имитации разумной даты создания):

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 триггер, который ничего не делает, таким образом делая его доступным только для чтения. Текущее представление имеет instead of триггеры, которые управляют базовой структурой. В частности, update Триггер выполняет вставку новой версии вместо фактического обновления.

Это выглядит несколько сложным, но среди преимуществ

  • он использует нормализацию, о которой разработчики уже знают.
  • версии не зависят друг от друга, то есть, когда вставляется новая версия, ни одна из других версий не должна изменяться каким-либо образом.
  • если в будущем запланировано изменение, вы можете продолжить и ввести изменение с установленным на эту дату датой вступления в силу. Текущая версия остается текущей до тех пор, пока не наступит момент, когда запланированная версия станет новой текущей версией.
  • Требуется небольшая модификация, чтобы получить полный двухвременный доступ к данным. Не похоже, что это то, что вам нужно, но вы никогда не знаете.

Примечание: чтобы использовать возможность "будущая версия", просто добавьте and Effective <= Sysdate в подзапрос текущего представления.

Другие вопросы по тегам