На данный момент в моей голове при фразе "у нас есть N документов с разными полями: какие-то дублируют друг-друга, какие-то наследуют, какие-то ничем не отличаются, но все же разные" я сразу же представляю как что-то через не-реляционные отношения или, на крайний случай, таблица с jsonb полем, где мы бы хранили разнообразные атрибуты.
Здесь же я пытаюсь пофантазировать на тему универсальности документов в ИС(читай - любых сущностей) и создание той самой гибкости через строгие реляционные отношения.
Пусть у нас существуют N документов с M атрибутами.
Множества атрибутов каждого документа M1, M2, M3, ..., Mn могут:
- не пересекаться: документы абсолютно не совпадают по атрибутам
- быть вложенными: документ А содержит часть полей из документа Б
- полностью эквивалентными: документ А содержит такой же набор полей как документ Б но с другими наименованиями/отображением
Следовательно, атрибуты и документы должны быть разнесены и связаны. Связь между ними будет выстраивать человек.
-- Пользователи
insert into users values(1, 'Иванов');
insert into users values(2, 'Петров');
-- Документы
insert into doc_type values (1, 'passport', 'Паспорт Гражданина РФ');
insert into doc_type values (2, 'snils', 'СНИЛС');
insert into doc_attribute values (1, 'series', 'То самое!');
insert into doc_attribute values (2, 'number', 'Вообще не то..');
-- Связь между атрибутаи и документа для конструктора
insert into doc_types_attributes values (1, 1, 'Серия паспорта');
insert into doc_types_attributes values (1, 2, 'Номер паспорта');
insert into doc_types_attributes values (2, 2, 'Страховой номер');-- выберите тип документа который хотите сохранить
select * from doc_type;
-- Иванов(users.id=1) хочется сохранить паспорт РФ(doc_type.id=1)
insert into doc values (1, 1, 1);
--заполните необходимые поля для паспорта (doc_type.id == 1)
-- 1. список всех полей + их наименование
select * from doc_types_attributes
where doc_types_attributes.type_id = 1;
-- 2. заполните значения: серия
insert into docs_attributes values (1, 1, '12 34');
-- 3. заполните значения: номер
insert into docs_attributes values (1, 2, '567890');
-- тут мне не нравится монструозный селект
-- ваши документы (Иванов)
select description from doc
join doc_type
on doc.type_id = doc_type.id
where doc.user_id = 1;
-- выбран документ Паспорт (просмотр значений)
select doc_types_attributes.description, docs_attributes.value, doc_attribute.name, doc_attribute.description
from docs_attributes
join doc_types_attributes
on docs_attributes.attribute_id = doc_types_attributes.attribute_id
and doc_types_attributes.type_id = (
select type_id from doc where id = docs_attributes.doc_id
)
join doc_attribute
on docs_attributes.attribute_id = doc_attribute.id
where docs_attributes.doc_id = 1;