Горизонтальная декомпозиция
Поясним сущность метода. Широко распространенный метод декомпозиции отношений, основанный на 1 – 5 НФ, БКНФ и даже 6 НФ, введенной в работе , заключается в декомпозиции отношений на два или более отношений таким образом, что предикат, соответствующий первоначальному отношению, “разбивается” с помощью удаления конъюнкций. Обратный оператор соединения таблиц JOIN – это реляционный аналог логического оператора AND (конъюнкции). Грубо говоря, “линии”, разделяющие отношение, расположены вертикально между атрибутами отношения. Назовем такую декомпозицию вертикальной.
Рассуждая по аналогии, можно предположить способ декомпозиции такой, что предикат, соответствующий первоначальному отношению, “разбивается” с помощью удаления дизъюнкций. Тогда реляционным аналогом логического оператора OR (дизъюнкции) будет оператор UNION. В этом случае “линии”, разделяющие отношение, расположены горизонтально между кортежами отношения. Назовем такую декомпозицию горизонтальной.
Как мы уже отмечали, отсутствующая информация может быть нескольких различных видов, например, “неизвестно”, “отсутствует” и “не применимо”, которые в настоящее время обозначаются одним способом с помощью маркера NULL. С помощью горизонтальной декомпозиции отношение, содержащее отсутствующую информация различного рода, декомпозируется на несколько отношений, одно из который не содержит отсутствующей информации, второе – содержит значения “не применимо”, третье – “отсутствует”, четвертое - “неизвестно” и т.д. Обратная композиция в “традиционный’ вид осуществляется с помощью оператора UNION. Поясним на примере некоторой ведомости, приведенном на рис. 1.
PERSONAL_INFO | |||
ID | NAME | JOB | SAL |
1034 | Анин | Юрист | 100000 |
1035 | Борисов | Почетный президент | NULL |
1036 | Семенов | NULL | 50000 |
1037 | Давиденко | NULL | NULL |
Рис. 1. Тестовый пример некоторой ведомости – исходная таблица PERSONAL_INFO.
Как видно из примера, таблица содержит два вида отсутствующей информации - “неизвестно” в случае с должностью Семенова и размером жалования Борисова, и “не применимо” в случае должности и жалования Давиденко (по условиям задачи, он - безработный).
Предикат отношения PERSONAL_INFO
мог бы выглядеть так: “человек, идентифицируемый как 1034, имеет фамилию Анин, занимает должность юриста и имеет жалование 100000 руб.”. В то же время предикат “человек, идентифицируемый как 1036, имеет фамилию
Семенов, занимает должность ? и имеет жалование 50 000
руб.” не имеет явного смысла. Кроме того, неизвестно даже точно, какому типу данных принадлежит этот “?”, поскольку, как отмечают Дейт и Дарвен, NULL не принадлежит никакому домену (типу данных), и не является значением
в общепринятом контексте этого понятия.
Первая стадия включает вертикальную декомпозицию этого отношения, как показано на рис. 2.
CALLED | DOES_JOB | EARNS | |||
ID | NAME | ID | JOB | ID | SAL |
1034 | Анин | 1034 | Юрист | 1034 | 100 000 |
1035 | Борисов | 1035 | Почетный президент | 1035 | NULL |
1036 | Семенов | 1036 | NULL | 1036 | 50 000 |
1037 | Давиденко | 1037 | NULL | 1037 | NULL |
Теперь отношение PERSONAL_INFO
декомпозировано на три отношения: CALLED, DOES_JOB, EARNS. Каждое из полученных в результате отношений характеризуется определенным предикатом. Предикат отношения CALLED выглядит так: “человек, идентифицируемый как ID, имеет фамилию NAME ”. Предикат отношения DOES_JOB
: “человек, идентифицируемый как ID, занимает должность JOB ”. Предикат отношения EARNS: “человек, идентифицируемый как ID, имеет жалование SAL”. Но предикаты отношений DOES_JOB и EARNS все еще не до конца приемлемы.
Вторая стадия – горизонтальная декомпозиция (рис. 3, 4).
DOES_JOB | JOB_UNK | UNEMPLOYED | ||
ID | JOB | ID | ID | |
1234 | Юрист | 1236 | 1237 | |
1235 | Почетный президент |
Рис. 3. Стадия 2 - горизонтальная декомпозиция отношения DOES_JOB.
EARNS | SAL_UNK | UNSALARIED | |
ID | SAL | ID | ID |
1234 | 100000 | 1235 | 1237 |
1236 | 70000 |
В окончательном варианте нами получены отношения DOES_JOB, JOB_UNK, UNEMPLOYED, EARNS, SAL_UNK, UNSALARIED, удовлетворяющие реляционной модели Третьего Манифеста . Им соответствуют предикаты: “человек, идентифицируемый как ID, занимает конкретную должность JOB”, “ человек, идентифицируемый как ID, занимает некоторую должность, но мы не знаем, какую”, “ человек, идентифицируемый как ID, является безработным”, “ человек, идентифицируемый как ID, имеет определенное жалование SAL”, “ человек, идентифицируемый как ID, имеет некоторое жалование, но неизвестно, какое”, “ человек, идентифицируемый как ID, не получает жалования”.
Сделаем ряд комментариев к проделанному:
В приведенном примере нами рассматривались только два вида отсутствующей информации, но метод допускает обобщение на большее их число.
Проведенная декомпозиция сохраняет первичные и внешние ключи и ограничения целостности.
Возможен и другой вариант горизонтальная декомпозиция отношений, в некоторых практических случаях более удобный, так как позволяет сократить количество результирующих отношений. Он изображен на рис. 5, 6.
DOES_JOB | JOB_UNK | ||
ID | JOB | ID | REASON |
1234 | Юрист | 1236 | UNKNOWN |
1235 | Почетный президент | 1237 | UNEMPLOYED |
EARNS | SAL_UNK | ||
ID | SAL | ID | REASON |
1234 | 100000 | 1235 | UNKNOWN |
1236 | 70000 | 1237 | UNSALARIED |
Определение традиционно выглядящего представления на основе полученных таблиц представлена на рис. 7, его внешний вид – на рис. 8.
CREATE VIEW r1 AS SELECT tmp.* FROM ( (SELECT earns.id, CAST(earns.sal AS varchar(40)) AS SAL FROM earns) UNION (SELECT sal_unk.id, CAST(sal_unk.reason AS varchar(40)) FROM sal_unk) ) AS tmp GO
CREATE VIEW r2 AS SELECT tmp.* FROM ( (SELECT does_job.id, does_job.job AS JOB FROM does_job) UNION (SELECT job_unk.id, job_unk.reason FROM job_unk) ) AS tmp GO
CREATE VIEW personal_info_v AS SELECT r1.id, called.name, r2.job, r1.sal FROM ((r1 JOIN r2 ON r1.id = r2.id) JOIN called ON r2.id = called.id) GO
DROP VIEW r1
DROP VIEW r2
Рис. 7. Фрагмент кода, реализующий определение представления PERSONAL_INFO_V на основе таблиц, полученных в результате горизонтальной декомпозиции, в синтаксисе диалекта SQL MS SQL Server.
Рис. 8. Представление PERSONAL_INFO_V после соединения таблиц
Рис. 9. Начальный вариант таблицы publishers БД Pubs.
Поле “state” этой таблицы содержит как значение штата, так и NULL в значении “неизвестно” в строке с pub_id = 9998, и NULL в значении “не применимо” в строках с pub_id = 9901, 9999.
Действуя по этой технологии, таблица publishers БД Pubs, начальный вариант которой рассмотрен на Рис. 9, превратится в набор таблиц:
- PUBLISHERS
{ pub_id, pub_name, city, country } - STATE
{ pub_id, state } - STATE_UNK
{ pub_id } - STATE_NONE
{ pub_id }.