Проектирование базы данных — Как связать таблицу с двумя другими уникальным способом?

#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, но не обоих? Затем вы (в своей бизнес-логике) интерпретируете NULL Products.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
  

Есть уникальный индекс (идентификатор контакта, идентификатор продукта). Вы также можете иметь уникальный индекс (идентификатор продукта, идентификатор контакта).

Ваше приложение должно определить, в какую таблицу соединений добавить строку ассоциации.