#mysql #database #database-design
#mysql #База данных #проектирование базы данных
Вопрос:
У меня возникли проблемы с проектированием базы данных, в которой одна таблица может быть связана с двумя другими таблицами однозначно.
У меня есть три таблицы.
Группы
id_group, name, contact_id
Продукты
id_product, id_group, name, contact_id
Контакты
contact_id, phone
Каждый продукт может быть независимым или принадлежать группе. В случае принадлежности к группе продукт наследует групповой контакт.
Первая проблема заключается в том, что контакт должен быть уникальным и может относиться только к таблице групп или таблице продуктов, но не к обеим одновременно.
Вторая проблема заключается в том, как мне заменить контакт продукта контактом группы, если продукт принадлежит группе, используя sql-запрос.
Может ли кто-нибудь помочь мне с этим?
Комментарии:
1. Может ли это быть так же просто, как ПРОВЕРКА
Products
соблюдения толькоid_group
этого илиcontact_id
NOT NULL, но не обоих? Затем вы (в своей бизнес-логике) интерпретируете NULLProducts.contact_id
как необходимость поискаGroups.contact_id
, который может быть аккуратно инкапсулирован в представлении.
Ответ №1:
Вашу первую проблему нелегко решить, используя логику в базе данных. Возможно, вам лучше выполнить эту проверку на уровне приложения.
Второй вопрос намного проще, хотя зависит от используемого вами SQL. любое из следующих действий будет работать в MySQL и T-SQL:
-- This way might be slower since the optimizer wouldn't know which contact_id index to use but would be ok on smallish tables.
SELECT
p.id_product,
p.id_group,
p.name,
c.*
FROM
Products p
LEFT JOIN
Groups g
ON
p.id_group = g.id_group
INNER JOIN
Contact c
ON
COALESCE(p.contact_id, g.contact_id) = c.contact_id;
-- This is a bit more long winded, but might be quicker to run on larger tables
-- as long as your indexes are setup right
SELECT * FROM
(
SELECT
p.id_product,
p.id_group,
p.name,
c.*
FROM
Products p
INNER JOIN
Groups g
ON
p.id_group = g.id_group
INNER JOIN
Contact c
ON
g.contact_id = c.contact_id
UNION
SELECT
p.id_product,
p.id_group,
p.name,
c.*
FROM
Products p
INNER JOIN
Contact c
ON
p.contact_id = c.contact_id
WHERE
p.id_group IS NULL) AS t;
Ответ №2:
Давайте начнем с перечисления связей между контактами, группами и продуктами.
-
У контакта может быть много групп или продуктов.
-
У группы может быть много контактов.
-
В группе может быть много продуктов.
-
Продукт может принадлежать нулю или одной группе.
-
У продукта может быть много контактов.
Когда у вас есть отношения «многие ко многим», вы используете таблицу соединений для установления соединения.
Давайте определим таблицы контактов, групп и продуктов.
Contact
-------
Contacj ID
Contact Name
Contacy Address
Contact Telephone
Contact Email
...
Group
-----
Group IG
Group Name
Product
-------
Product ID
Product Name
Group ID (FK)
В этих таблицах контактная информация находится в одном месте, в таблице Cibtact.
Теперь давайте создадим таблицу соединений, чтобы связать контакты и группы вместе.
ContactGroup
------------
ContactGroupID
Contact ID
Group ID
Есть уникальный индекс (идентификатор контакта, идентификатор группы). У вас также может быть уникальный индекс (идентификатор группы, идентификатор контакта).
Вот таблица соединений для контакта и продукта.
ContactProduct
--------------
ContactProduct ID
Contact ID
Product ID
Есть уникальный индекс (идентификатор контакта, идентификатор продукта). Вы также можете иметь уникальный индекс (идентификатор продукта, идентификатор контакта).
Ваше приложение должно определить, в какую таблицу соединений добавить строку ассоциации.