Как разделить эту существующую таблицу базы данных, чтобы уменьшить избыточность
У меня есть таблица, которая слишком велика для обработки. Я пытался разделить его на две таблицы, но все еще не удовлетворен.
Вот как выглядит таблица, (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
в подзапрос текущего представления.