Проблемы с проектированием базы данных, связанные со связями

StackOverflow https://stackoverflow.com/questions/163400

Вопрос

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

Основная логика предусматривает следующее:

  1. Пользователи получают доступ к онлайн-тренингам через Места.Пользователи могут занимать несколько мест.
  2. Места приобретаются компаниями и имеют отношение "многие ко многим" к Продуктам.
  3. Продукт имеет отношение "многие ко многим" с Модулями.
  4. Модуль имеет отношение "многие ко многим" к Урокам.
  5. Уроки - это доступ конечных пользователей к своему обучению.
  6. Чтобы замутить ситуацию, по той или иной причине у некоторых Пользователей есть несколько Мест с одними и теми же Продуктами.
  7. Сертификация проводится для каждого Продукта, а не для каждого Места.
  8. Пользователи имеют отношение "многие ко многим" к урокам, в котором хранится их текущий статус или оценка за урок.
  9. Пользователи сертифицируют Продукт, когда они завершают все Уроки во всех Модулях для Продукта.
  10. Также важно знать, когда Пользователь завершил все Уроки по определенному Модулю.
  11. Некоторые места будут предназначены для повторной сертификации, что означает, что Пользователи, ранее прошедшие сертификацию на Продукт, могут зарегистрироваться и сдать экзамен на повторную сертификацию.
  12. В соответствии с правилом 11 пользователи могут иметь и будут иметь несколько записей сертификации.
  13. Редактировать:Когда Пользователь завершает Урок (оценка превышает 80%), это означает, что Пользователь (в соответствии с текущей бизнес-логикой) завершил Урок для всех Продуктов и всех Мест, содержащих Урок.

Проблема, с которой я продолжаю сталкиваться при текущем дизайне и бизнес-логике, как я их более или менее описал, заключается в том, что я не могу найти способ эффективно связать, сертифицирован ли пользователь для конкретного продукта и места, с тем, когда у него их нет.Я продолжаю натыкаться на препятствия, пытаясь установить, какие Продукты под какими Сиденьями сертифицированы для Пользователя, а какие нет.Частично проблема заключается в том, что если в данный момент они зарегистрированы для нескольких товаров одного и того же вида под разными сиденьями, то мне приходится подсчитывать Товар только один раз.

Ниже приведена копия той части схемы, которая задействована.Будем признательны за любые предложения о том, как улучшить дизайн или нарисовать ассоциацию в коде.На случай, если это имеет значение, этот сайт построен на стеке LAMPP.

Вы можете просмотреть соответствующую часть схемы базы данных здесь: http://lpsoftware.com/problem_db_structure.png

Это было полезно?

Решение

Вам нужно реляционное разделение Не реализовано непосредственно в SQL, но это может быть сделано. Найдите в Google другие примеры.

Другие советы

После быстрого взгляда на схему я думаю, что одна из вещей, которые вы можете сделать, - это создать таблицу to_be_certified. Заполните его user_id, product_id и seat_id, когда продукт назначен на место (когда заполнен product_seat_rtab).

При добавлении записи в таблицуtification_rtab удалите соответствующую запись в таблице to_be_certified. Это даст вам легкий доступ ко всем продуктам, которые сертифицированы для пользователей, и к тем, которые не сертифицированы.

Чтобы избавиться от дубликатов product_id, вы можете группировать по product_id.

Вам нужно внести изменения в таблицу lessonstatus_rtab:

CREATE TABLE lessonstatus_rtab (
  user_id    INT NOT NULL,
  seat_id    INT NOT NULL,
  lesson_id  INT NOT NULL REFERENCES lesson_rtab,
  accessdate TIMESTAMP,
  score      NUMERIC(5,2) NOT NULL DEFAULT 0,
  PRIMARY KEY (user_id, seat_id, lesson_id),
  FOREIGN KEY (user_id, seat_id) REFERENCES user_seat_rtab (user_id, seat_id)
);

Затем вы можете запросить каждый продукт, на который у пользователя есть место, он сертифицирован? Это предполагает, что количество уроков, которые он набрал, скажем, 50% или выше, совпадает с количеством уроков во всех модулях продукта.

SELECT p.name, us.user_id, us.seat_id, COUNT(l.id) = COUNT(lu.lesson_id) AS is_certified
FROM user_seat_rtab AS us
 JOIN seat_rtab AS s ON (s.id = us.seat_id)
 JOIN product_seat_rtab AS ps ON (ps.seat_id = s.id)
 JOIN product_rtab AS p ON (p.id = ps.product_id)
 JOIN product_module_rtab AS pm ON (pm.product_id = p.id)
 JOIN module_rtab AS m ON (m.id = pm.module_id)
 JOIN module_lesson_rtab AS ml ON (ml.module_id = m.id)
 JOIN lesson_rtab AS l ON (l.id = ml.lesson_id)
 LEFT OUTER JOIN lessonstatus_rtab AS lu 
   ON (lu.lesson_id = l.id AND lu.user_id = us.user_id 
     AND lu.seat_id = us.seat_id AND lu.score > 0.50)
GROUP BY p.id, us.user_id, us.seat_id;

Обновить:

Я дополнительно рассмотрел этот вопрос и рассмотрел, позволит ли это работать лучше, если просто удалить таблицу user_seat_rtab, а затем использовать эквивалентную таблицу certification_rtab (возможно, переименованную) для хранения всей информации о статусе места пользователя.Таким образом, устанавливается прямая связь между Пользователем, его Местом, каждым Продуктом в пределах Места и тем, сертифицирован ли Пользователь для конкретного Продукта и Места.

Поэтому я бы применил следующие изменения к схеме, опубликованной вместе с вопросом:

DROP TABLE user_seat_rtab;
RENAME TABLE certification_rtab TO something_different;

Альтернативой дальнейшей нормализации этой новой структуры было бы сделать что-то вроде этого:

ALTER TABLE user_seat_rtab 
    DROP PRIMARY KEY;
    ADD COLUMN product_id int(10) unsigned NOT NULL;
    ADD CONSTRAINT pk_user_seat_product PRIMARY KEY (user_id, seat_id, product_id);
    ADD CONSTRAINT fk_product_user_seat FOREIGN KEY (product_id) REFERENCES product_rtab(id) ON DELETE RESTRICT;

Я не совсем уверен, решит ли это проблему или это просто немного изменит характер проблемы, вводя новые.Итак, есть ли у кого-нибудь еще какие-либо критические замечания или предложения?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top