Дизайн базы данных: рекурсивные отношения «многие ко многим» - PullRequest
2 голосов
/ 16 сентября 2010

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

Например, у меня может быть три таблицы, где n равно 3:

Parking_Lot
Car
Person

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

Чтобы смоделировать это, у вас будет 3 таблицы (Lot, Car, Person) и три таблицы взаимосвязей.

Скажем, вы добавили четвертый стол с едой. Пищу можно есть на многих парковках, во многих автомобилях и у многих людей. Это занимает 4 таблицы + 6 = 10 таблиц.

Как вы моделируете такие отношения, не создавая большое количество промежуточных таблиц?

Меня больше интересует эта концепция, но я в основном использую c #, поэтому, если есть удачная возможность выполнить это в .net, я весь слух.

Ответы [ 8 ]

3 голосов
/ 16 сентября 2010

Я бы решил это, используя почти полиморфный подход.Вы можете просто использовать две таблицы, например:

CREATE TABLE Node (id UNIQUEIDENTIFIER NOT NULL, PRIMARY KEY (id));
CREATE TABLE Relationships (
    parent UNIQUENIDENTIFIER NOT NULL, 
    child UNIQUEIDENTIFIER NOT NULL,
    CONSTRAINT FK_Relationship_ParentNode
        FOREIGN KEY (parent) REFERENCES Node(id),
    CONSTRAINT FK_Relationship_ChildNode
        FOREIGN KEY (child) REFERENCES Node(id)
);

Тогда все ваши другие сущности "наследуются" от узла:

CREATE TABLE Person (
    id UNIQUEIDENTIFIER NOT NULL,
    name NVARCHAR(50) NOT NULL,
    CONSTRAINT FK_Person_Node
        FOREIGN KEY (id) REFERENCES Node(id)
);

CREATE TABLE ParkingLot (
    id UNIQUEIDENTIFIER NOT NULL,
    name NVARCHAR(50) NOT NULL,
    address NVARCHAR(250) NOT NULL, -- bad way to model
    CONSTRAINT FK_ParkingLot_Node
        FOREIGN KEY (id) REFERENCES Node(id)
);

CREATE TABLE Food (
    id UNIQUEIDENTIFIER NOT NULL,
    name NVARCHAR(50) NOT NULL,
    calories INT NOT NULL, -- hopefully only needs an int ;)
    CONSTRAINT FK_Food_Node
        FOREIGN KEY (id) REFERENCES Node(id)
);

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

Например, если вы хотите найти, какие продукты принадлежат тем или иным людям, вы можете сказать:

SELECT p.name AS person, f.name AS food
FROM Person AS p
INNER JOIN Relationships AS r
ON r.parent = p.id
INNER JOIN Food AS f
ON f.id = r.child

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

1 голос
/ 16 сентября 2010

как обычно, "это зависит" -

это зависит от того, что вы собираетесь делать с информацией

в нормализованном представлении таблицы сопоставления необходимы для того, чтобы отличать (предположительно, обогащенные данными) отношения друг от друга

в представлении базы знаний будет достаточно одной типизированной таблицы отношений, хотя для этого потребуется разыменовать исходный и целевой идентификаторы в разных таблицах

0 голосов
/ 30 июня 2019

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

таблица 1 = «вещи», в которые вы складываете людей, автомобили, места для парковки, еду - все в одну таблицу, добавляете столько столбцов, сколько вам нужно

таблица 2 = «отношения вещей», где вы можетесопоставить человека с автомобилем, человека с парковкой, еду с автомобилем и т. д ....

таблица 3 = "категории", то есть человек, парковка, машина, еда

таблица 4 = "отношение категории", где вы определяете категорию для каждой вещи

возможно, я ошибаюсь, ИДК, но кажется лучшим решением, если вы не хотите экспоненциального числа таблиц

0 голосов
/ 16 сентября 2010

Я полагаю, вам нужно менее 10 таблиц. Рассмотрим человека A, который ест пищу X. Если человек A находится на стоянке B, то еда X съедается на той же парковке B; поэтому вам, возможно, не понадобится таблица с информацией о еде и парковке.

0 голосов
/ 16 сентября 2010

Как и все говорили, этот ответ полностью зависит от того, что вы делаете и почему вы это делаете.

Базы данных отлично подходят для извлечения наборов данных, а также для категоризации и обобщения этих данных. Вот для чего они предназначены (среди многих других вещей).

Они не очень хорошо описывают сложные отношения между отдельными ценностями (x глубокие отношения n: m). Структуры произвольного доступа из движения NoSQL лучше в этом.

Если вы действительно хотите использовать классическую СУБД, вы можете смоделировать проблему в виде графа в БД, используя концепцию ребер и узлов. Узлы имеют 0: N ребер и 0: N атрибутов / значений (EAV, как предложено выше). Края имеют 2 узла и, возможно, вес.

Вы можете смоделировать это с:

NODE ([node_id, entity, attribute], value)
EDGE ([src_node_id, dest_node_id], weight)

Создание отношения между узлами (ребро) требует простого добавления значения в таблицу EDGE.

Обход структуры требует рекурсивного набора запросов, которые находят все возможные шаги текущего узла и затем выбирают один, чтобы перейти к следующему узлу. Это может быть интенсивно для СУБД.

EG //

SELECT dest_node_id 
FROM EDGE 
WHERE src_node_id = <<This Node ID>> 
ORDER BY weight ASC 
LIMIT 1

Вспенить, промыть и повторить для того, насколько далеко вы хотите идти (это предполагает, что вес - это стоимость, а не показатель выгоды, и что график является ориентированным графом).

0 голосов
/ 16 сентября 2010

Люди обычно связывают системы с базами данных (особенно с правильным моделированием), включая постоянство ACID, что немаловажно.С другой стороны, .net является платформой для приложений и не имеет ничего общего с персистентностью (он может использовать разные бэкэнды для персистентности).Так что, если вы не уверены, что вам нужна полная СУБД или вы хотите поговорить в структурах памяти, то на ваш вопрос, который сложно начать, действительно нет ответа.

В противном случае явное моделирование n плюс все таблицы бинарных отношений считается плюсом.

Кроме того, вы упоминаете n плюс таблицы отношений, как если бы это была какая-то универсальная модель.Однако это не учитывает троичные отношения или отношения более высокого порядка, а также не учитывает множественные двоичные отношения (или множественные отношения более высокого порядка).

Я уверен, что кто-то предложит модель EAV или какое-то расширение.

Проблема в том, что при таком подходе вы приобретаете гибкость, но теряете способность фактически реализовывать отношения.

Все зависит от того, зачем и для чего вам нужна эта стойкость,

Вы можете создать своего рода гибрид - например, автоматизировать создание таблиц на основе центральной таблицы, описывающей ваши отношения.Если вы хотите базу данных.Реляционная база данных.

Подобные вещи можно выполнять и с XML, или с некоторыми платами объектно-реляционного отображения и т. Д. *

Вам необходимо лучше определить проблему.

0 голосов
/ 16 сентября 2010

Вы можете попробовать иметь центральную таблицу отношений с одним столбцом для каждой имеющейся у вас таблицы сущностей (допускается NULL). Для каждой комбинации есть строка с соответствующими идентификаторами.

Это сложно, но может позволить вам также моделировать многоплановые отношения - например, человек A за рулем автомобиля B на стоянке C. Возможно, вы захотите добавить какой-либо тег, например, провести различие между «лицом A, управляющим автомобилем B на стоянке C», и «лицом A, владеющим автомобилем B, который припаркован на участке C».

0 голосов
/ 16 сентября 2010

вы можете создать таблицу отношений с идентификатором типа / именем таблицы.

relationship
      relationship_type_parent
      relationship_id_parent
      relationship_type_child
      relationship_id_child 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...