Дизайн базы данных для многих-многих ревизий? - PullRequest
0 голосов
/ 22 августа 2011

Мой вопрос связан с Дизайн базы данных для редакций? , но более сложный.

У меня есть две таблицы с отношениями «многие ко многим». Давайте назовем их А и Б.

A: A.id, A.data, A.last_change_time
B: B.id, B.data
A_B: A_B.A_id, A_B.B_id, A_B.connected_since_time, A_B.some_status_enum

Таблица соединителей A_B должна поддерживать ревизии. Если связь между элементом в A и элементом в B удалена, необходимо сохранить историческую информацию, существовавшую ранее. Если статус соединения изменяется, необходимо сохранить историческую информацию о старом статусе.

Вот некоторые отчеты, которые мне нужно сгенерировать:

  1. Список всех элементов в A, которые вообще не связаны с B (сейчас).
  2. Список всех элементов в A, которые связаны хотя бы с одним элементом в B с определенным статусом.
  3. Список всех пар A-B, которые когда-то были подключены, но больше не подключены.
  4. Список всех соединений A-B, где время последнего изменения A наступает после времени соединения.
  5. Количество всех подключений A-B, где время последнего изменения A - после времени подключения, сгруппированного по статусу.

Я подумал просто добавить булево поле A_B.is_current в таблицу соединений. Когда соединение удаляется, я просто устанавливаю is_current в false. При изменении статуса я устанавливаю для is_current значение false для старых записей и добавляю новую запись с новым статусом.

Ответы на подобные ранее заданные вопросы часто утверждают, что «is_current» - это плохой дизайн, и должно быть лучшее решение. Предыдущие решения говорили о пересмотре записи в одной таблице, а не об отношениях между ними.

Неправильно ли использовать столбец is_current для отслеживания истории соединений «многие ко многим»? Если это неправильно, какие проблемы это может вызвать? Какое решение лучше?

Ответы [ 2 ]

1 голос
/ 22 августа 2011

Обычно ...

  • имеет 2 дополнительных столбца: ValidFromDateTime и ValidToDateTime
  • тогда первичный ключ A_id, B_id, ValidFromDateTime
  • ValidToDateTime может бытьNULL или значение дозорного (например, 99991231)

Когда происходит новая ревизия, вы заполняете ValidToDateTime «текущей строки» и добавляете новую строку с тем же значением даты и времени для ValidFromDateTime.Или просто установите ValidToDateTime, если это ваше бизнес-правило.

Это дает вам состояние и (или отсутствие) состояния на любой момент времени

Тогда ваши запросы довольно просты

  1. NOT EXISTS для A_ID
  2. EXISTS для A_ID
  3. EXISTS для A_ID с ValidToDateTime NOT NULL (нет текущей строки)
  4. EXISTS для A_ID, также сравнивающего ValidToDateTime и last_change_time
  5. LEFT JOIN (те же условия, что и для 4) с совокупностью
0 голосов
/ 22 августа 2011

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

...