Многие-ко-многим без промежуточной таблицы-возможно ли это?

У меня есть две сущности, которые обычно имеют отношение один ко многим, но в редких случаях должны иметь возможность быть многими ко многим. Я не хочу присоединять таблицы с промежуточной таблицей для каждого запроса - и я думаю, что есть предпочтительные шаблоны для "редких многих ко многим",-(возможно, с дополнительной таблицей для m-t - m, с дубликатами записей или что-то еще). Есть идеи?

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

7 ответов


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

Ренди


что не так с отношениями "многие ко многим"? Это самый простой способ решить проблему, и присоединение к таблицам будет очень быстрым, если индексы установлены правильно. И не беспокойтесь о времени кодирования - вы можете разложить соединение на множители, так что вам нужно написать его только один раз. Если вы используете Linq-подобное программное обеспечение, вы можете хранить подзапросы. Если вы создаете строки SQL вручную, вы все равно можете сохранить подзапрос как строку const где-то в своей программе.

, вы можете избежать дополнительной таблицы, создав два столбца "первичный ребенок" и "вторичный ребенок", где первичный ребенок не равен NULL, а вторичный ребенок-NULLable. Если вас не волнует возможность нескольких совпадений, выберите только первичный дочерний элемент. В редких случаях, когда это имеет значение, выберите обоих детей.

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

Я думаю, что вы делаете. Индексированные соединения-это то, в чем базы данных особенно хороши.

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

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

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


Я собираюсь предположить, что ваш вопрос касается реляционных (SQL, например) баз данных. Если вы хотите смоделировать таблицу в "нормальной" форме, требуется промежуточная таблица. Но, без ограничения нормальности, вы можете смоделировать свой случай с помощью одной таблицы с m * n строками (результат внутреннего соединения, если у вас была таблица A, промежуточная таблица и таблица B. Это может быть полезно в операциях хранения данных, но я бы не предложил использовать эту стратегию, если бы таблица была часто строки удаляются, обновляются или вставляются.


В общем, вы не сможете избежать промежуточная таблица. Что бы вы ни делали, чтобы сделать случай "один ко многим" проще, это будет стоить вам больше усилий, чтобы справиться с общим случаем m:n правильно.


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


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

План-схема:

create table t1 (id integer, xref_t2 set(integer), ...other columns...);
create table t2 (id integer, xref_t1 set(integer), ...other columns...);

обратите внимание, что нет простого способа объявить ссылочную целостность ограничение, чтобы гарантировать, что значения в 'xref_t2' действительно все еще действительны (или написать триггер для принудительного применения ограничения).

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

лучший способ сделать это с явная таблица ассоциаций.