Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Проектирование БД Новый топик    Ответить
 Как реализовать "исторического изменения" объекта в БД  [new]
kormot
Member

Откуда:
Сообщений: 249
Добрый день Товарищи!

Скажите пожалуйста, при проектировании такой БД:
Есть Объект, есть Владелец Объекта и есть Отчёт по Объекту.

Как сделать, чтобы при смене у Объекта его Владельца:
В базе бы сохранялось для Отчётов по Объекту, ну или для других связей с Объектом на данный момент, что его Владелец такой-то?

Т.е. при построении Отчёта за период когда был другой Владелец, чтобы это было отражено.

Предварительно есть несколько вариантов, как это реализовывать, но чтобы не наступать на грабли, хочу свериться с теми, кто знает верное решение :)
Object (
    id           SERIAL,
    objName      CHAR(50)
)

Owner (
    id           SERIAL,
    ownName      CHAR(50)
)

//1. Первый вариант - хранить просто активную связь Владелец-Объект и в отчётах указатель на данный ключ:
OwnerObject (
    id           SERIAL,
    ownID        BIGINT UNSIGNED,
    objID        BIGINT UNSIGNED,
    /* Для уникального объекта только одна запись с isActive=1, 
       при вставке предыдущие для данного objID устанавливать в 0 */
    isActive     TINYINT UNSIGNED DEFAULT 1, 
) 
Report (
    id           SERIAL,
    objOwnID     BIGINT UNSIGNED -> FK OwnerObject(id),
    repPeriod    DATETIME,
    repData      ......
)

//2. Второй вариант - просто, Владелец - это просто поле для Объекта, а в Отчёте указывать и objID и ownID
Report (
    id           SERIAL,
    objID        BIGINT UNSIGNED,
    ownID        BIGINT UNSIGNED,
    repPeriod    DATETIME,
    repData      ......
)

Ещё что-то в голову приходило.
11 сен 19, 12:59    [21968461]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
skyANA
Member

Откуда: Зеленоград
Сообщений: 26636
kormot,

если Report хранит состояние объекта на определённую дату, то вариант 2
то есть вы будете хранить тупо факт того, что было в определённый момент времени
11 сен 19, 13:22    [21968480]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
kormot
Member

Откуда:
Сообщений: 249
skyANA, спасибо!
11 сен 19, 13:41    [21968515]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
KreatorXXI
Member

Откуда: Москва
Сообщений: 783
kormot,

ИМХО, второй вариант имеет проблемы с целостностью данных. Нет идеи как построить внешний ключ? У меня нет. В конце концов проблема всплывёт.
Ну и предложение. Сделать таблицу "История Владельцев Объекта", где будет дата.
11 сен 19, 15:31    [21968611]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
kormot
Member

Откуда:
Сообщений: 249
KreatorXXI
ИМХО, второй вариант имеет проблемы с целостностью данных. Нет идеи как построить внешний ключ? У меня нет. В конце концов проблема всплывёт.
Ну и предложение. Сделать таблицу "История Владельцев Объекта", где будет дата.

А проблемы с целлостностью почему? Т.к. могут быть у отчёта (objID,ownID) такие, которые на самом деле между собой не связаны?

А в первом варианте, там как раз промежуточная таблица - это история связей между Владельцем и Объектом, и на эту связь делается у отчёта ключ, это в плане целостности имеет проблемы?
11 сен 19, 19:21    [21968850]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
iOracleDev
Member

Откуда:
Сообщений: 303
kormot,

Если отчет включает несколько смен объектом владельца, как будете собирать что включать в отчет а что нет?

Отчет за период, а где даты в ваших вариантах?

Оба ваших варианта неправильные, вот вам пара других вариантов:

Сначала плохой - можно в OwnerObject добавить
поля date_from и date_to, date_from - дата создания записи, date_to - для действующей записи константа например 01.01.4000 года (или какого нибудь другого сильно далекого года), когда у объекта меняется владелец старая запись закрывается присваиванием в date_to текущей даты, при этом date_from новой действующей записи должна быть равна date_to предыдущей плюс минимальный квант времени, для типа дата это скорее всего будет секунда (если будет несколько изменений в одну секунду будут проблемы:)).

Нормальный вариант - создать таблицу OwnerObjectHist, при изменении владельца объекта, старое состояние вставляется в таблицу истории изменений с датой до которой оно действовало, в OwnerObject текущее действующее состояние, естественно в таблице OwnerObjectHist свой id со своей последовательностью и внешний ключ на таблицу OwnerObject.
11 сен 19, 19:31    [21968858]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
iOracleDev
Member

Откуда:
Сообщений: 303
kormot
А проблемы с целлостностью почему?

Потому что вы не то протоколировать собираетесь, протоколировать нужно "первичку".
11 сен 19, 19:33    [21968861]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
kormot
Member

Откуда:
Сообщений: 249
iOracleDev
Если отчет включает несколько смен объектом владельца, как будете собирать что включать в отчет а что нет?

Ну, тут подразумевается, что смена владельца она очень нечастая. И отчёт строится и его результаты полученные на отчётный момент сохраняются, высчитывать их потом из первички не надо. Там сам отчёт формируемый к отчётному периоду и есть первичка. Т.е. условно заполняются поля отчёта на указанный период и когда отчёт закрывается, то все его заполнения и есть отчёт.

И соответственно если у данного отчёта за указанный (repPeriod) период связь с данным ownID - то нас в будущем вполне устраивает по заданному объекту получиться все отчёты с результатами, и в каждый период достаточно знать кто является владельцем данного отчёта.

Жесть как сложно написал. Масло маслом намазал и ещё маслица сверху добавил :)

По поводу добавления данных о временном периоде "владения" тем или иным объектом - эта информация не интересует. Главное в отчёте за данный период чтобы была информация кто владелец (связь отчёта по objOwnID например), и для заполнения текущих отчётов по объектам у владельца (это запись objID,ownID с isActive=1 в OwnerObject)


Второй предложенный вариант - он интересен, только я детали некоторые не понял. В итоге отчёт каждый должен ссылаться на запись в OwnerObjectHist или на OwnerObject?
Вроде в таком случае таблица OwnerObject - лишняя? Зачем она?
11 сен 19, 20:53    [21968905]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
iOracleDev
Member

Откуда:
Сообщений: 303
kormot
Жесть как сложно написал. Масло маслом намазал и ещё маслица сверху добавил :)

Не то слово.

kormot
По поводу добавления данных о временном периоде "владения" тем или иным объектом - эта информация не интересует. Главное в отчёте за данный период чтобы была информация кто владелец (связь отчёта по objOwnID например), и для заполнения текущих отчётов по объектам у владельца (это запись objID,ownID с isActive=1 в OwnerObject)

У тебя таблица OwnerObject лишняя, выкинь ее вообще или как минимум выброси из нее isActive, в отчет помещай не ссылку на нее, а просто objID и ownID.

kormot
Второй предложенный вариант - он интересен, только я детали некоторые не понял. В итоге отчёт каждый должен ссылаться на запись в OwnerObjectHist или на OwnerObject?
Вроде в таком случае таблица OwnerObject - лишняя? Зачем она?

Текущие актуальные отчеты строятся на основе текущих актуальных данных, они хранятся в операционной таблице, ретроспективные строятся либо на исторической таблице либо на объединении операционной и исторической таблиц, в зависимости от того как вести историческую таблицу.
11 сен 19, 21:42    [21968927]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
kormot
Member

Откуда:
Сообщений: 249
iOracleDev
У тебя таблица OwnerObject лишняя, выкинь ее вообще или как минимум выброси из нее isActive, в отчет помещай не ссылку на нее, а просто objID и ownID.

А выше же, второй вариант изначальный у меня - он же так и есть, отчёты с указанием для каждого objID и ownID, но ниже сказали что он имеет проблемы с целостностью данных?
12 сен 19, 09:04    [21969109]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
KreatorXXI
Member

Откуда: Москва
Сообщений: 783
kormot,

ну послушай, всё же просто. В таблице OwnerObject у objID=1 ownID=2. А в таблице Report objID=1 ownID=1. Никакой синхронизации на уровне базы. И не важно часто меняется собственник или не часто. Можно попробовать сделать внешний ключ (OwnerObject<->Report) по двум полям. Тогда база будет целостной. Но опять вопрос - как быть со старыми отчётами? Информация по истории, допустим, хранится, в отдельном файле. Но таблица Report ничего об этом не знает.
12 сен 19, 11:54    [21969279]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
Дмитрий Мух
Member

Откуда: Зеленоград
Сообщений: 2063
kormot
И отчёт строится и его результаты полученные на отчётный момент сохраняются, высчитывать их потом из первички не надо.

Под это подходит: "Второй вариант - просто, Владелец - это просто поле для Объекта, а в Отчёте указывать и objID и ownID".

На момент построения отчёта вы сохраняете факт того, кто является владельцем объекта.
Данные же вы не планируете терять, чтобы через год не понимать, кто был владельцем объекта в прошлом? :)
13 сен 19, 13:01    [21970271]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
Дмитрий Мух
Member

Откуда: Зеленоград
Сообщений: 2063
KreatorXXI
kormot,

ну послушай, всё же просто. В таблице OwnerObject у objID=1 ownID=2. А в таблице Report objID=1 ownID=1. Никакой синхронизации на уровне базы. И не важно часто меняется собственник или не часто. Можно попробовать сделать внешний ключ (OwnerObject<->Report) по двум полям. Тогда база будет целостной. Но опять вопрос - как быть со старыми отчётами? Информация по истории, допустим, хранится, в отдельном файле. Но таблица Report ничего об этом не знает.

Какая ещё синхронизации на уровне базы, целостность?

Отчёты должны содержать информацию о том, что в прошлом отчётном периоде владелец объекта был иной, чем в текущем.
Вариант хранить ownID в Report прекрасно решает эту задачу.

И целостность не нарушается, и синхронизация никакая не нужна.
13 сен 19, 13:07    [21970274]     Ответить | Цитировать Сообщить модератору
 Re: Как реализовать "исторического изменения" объекта в БД  [new]
iOracleDev
Member

Откуда:
Сообщений: 303
kormot
А выше же, второй вариант изначальный у меня - он же так и есть, отчёты с указанием для каждого objID и ownID, но ниже сказали что он имеет проблемы с целостностью данных?

Если верить тому что ты озвучил, тебя не интересует история кто когда и сколько владел объектом, грубо говоря OwnerObject используется только как текущая конфигурация и история по ней не сохраняется, проблемы с целостностью в том, что ты не сможешь выпустить отчет за прошлый период, информации о владельцах объектов за тот период просто нет, если по каким то причинам забыли запустить отчет ранее и захотят его получить в настоящий момент он может содержать неверную информацию. Исходя из твоих хотелок второй вариант выглядит вполне подходящим, OwnerObject либо не использовать вообще, либо использовать как конфигурационную текущую настройку, поскольку история изменений тебе на самом деле не нужна.
13 сен 19, 14:08    [21970354]     Ответить | Цитировать Сообщить модератору
Все форумы / Проектирование БД Ответить