Странные отношения многие ко многим и один ко многим - PullRequest
3 голосов
/ 23 октября 2008

Я знаю, что получу голоса, но я должен убедиться, логично это или нет.

У меня есть три таблицы A, B, C. B - это таблица, используемая для установления множества отношений между A и C. Но дело в том, что A и C также напрямую связаны в отношениях 1-многие

Клиент добавил следующее требование:

Получить информацию из внутреннего соединения таблицы B с A и C, и в том же запросе связать A и C в отношении один-много

Что-то вроде:

альтернативный текст http://img247.imageshack.us/img247/7371/74492374sa4.png

Я пытался выполнить запрос, но всегда возвращал 0 строк. Заказчик настаивает на том, что я могу выполнить это требование, но я сомневаюсь в этом. Есть комментарии?

PS. У меня не было более описательного названия, есть идеи?

UPDATE: Благодаря rcar, в некоторых случаях это может быть логичным, чтобы иметь историю всех классов, которые посещал студент (предположим, что студент может брать только один класс за раз)

UPDATE: Есть таблица для контактов, таблица с информацией о каждом контакте и таблица отношений. Чтобы получить информацию о контакте, я должен установить связь 1: 1 с информацией, и у каждого контакта может быть как и адресная книга; вот почему реализовано отношение «многие-многие».

Полная идея - получить имя контакта и его адресную книгу. Теперь, когда я понял идею клиента ... У меня проблемы с запросом, в основном я пытаюсь использовать запрос, который написал jdecuyper, но, как он предупреждает, я не получаю данных обратно

Ответы [ 6 ]

5 голосов
/ 23 октября 2008

Это выполнимый сценарий. Вы можете присоединиться к таблице дважды в запросе, обычно присваивая ей другой псевдоним, чтобы все было просто.

Например:

SELECT s.name AS "student name", c1.className AS "student class", c2.className as "class list"
FROM s
JOIN many_to_many mtm ON s.id_student = mtm.id_student
JOIN c c1 ON s.id_class = c1.id_class
JOIN c c2 ON mtm.id_class = c2.id_class

Это даст вам список имен всех учеников и «жестко закодированных» классов со всеми их классами из таблицы many_to_many.

Тем не менее, эта схема не имеет логического смысла. Из того, что я могу собрать, вы хотите, чтобы ученики могли иметь несколько классов, поэтому таблица many_to_many должна быть там, где вы хотите найти классы, связанные со студентом. Если записи id_class, используемые в таблице s, отличаются от записей в many_to_many (например, если s.id_class ссылается, скажем, на назначения классов в классе, которые появляются только в этой таблице, тогда как many_to_many.id_class ссылается на классы для кредита и исключает классы для классов), вместо этого вам лучше разбить c на две таблицы.

Если это не так, мне трудно понять, почему вы хотите, чтобы один класс был подключен к таблице s.

РЕДАКТИРОВАТЬ: Только что увидел ваш комментарий, что это была выдуманная схема, чтобы привести пример. В других случаях это может быть разумным способом сделать что-то. Например, если вы хотите отслеживать местоположения компании, у вас может быть таблица Company, таблица Locations и таблица стран. Таблица «Компания» может иметь ссылку «1-много» на «Страны», где вы будете отслеживать страну, в которой расположена штаб-квартира компании, но ссылку «многие ко многим» через «Места», где вы будете отслеживать каждое место, где у компании есть магазин.

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

3 голосов
/ 23 октября 2008

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

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

3 голосов
/ 23 октября 2008

Возможно, это недостаток кофеина, но я не могу придумать законную причину желания сделать это. В приведенном вами примере у вас есть ученики, классы и таблица, которая связывает их. Если вы думаете о том, что вы хотите, чтобы запрос выполнялся на простом английском языке, несомненно, он должен управляться либо таблицей student, либо таблицей class. т.е.

  • выберите все классы, которые посещает студент 1245235
  • выберите всех студентов, которые посещают класс 101

Можете ли вы объяснить это требование лучше? Если нет, скажите своему клиенту, чтобы смириться с этим. Имея отношения между студентами и классами напрямую (A и C), кажется чистым безумием, у вас уже есть таблица B, которая делает это ...

2 голосов
/ 23 октября 2008

Я полагаю, что s.id_class указывает текущий класс студента, в отличие от классов, которые она посещала в прошлом.

Решение, показанное rcar, работает, но оно повторяет c1.className в каждой строке.

Вот альтернатива, которая не повторяет информацию и использует на одно соединение меньше. Вы можете использовать выражение для сравнения s.id_class с текущим c.id_class, сопоставленным через таблицу mtm.

SELECT s.name, c.className, (s.id_class = c.id_class) AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
  JOIN c ON (c.id_class = mtm.id_class);

Таким образом, is_current будет 1 (true) в одной строке и 0 (false) во всех остальных строках. Или вы можете вывести что-то более информативное с помощью конструкции CASE:

SELECT s.name, c.className, 
  CASE WHEN s.id_class = c.id_class THEN 'current' ELSE 'past' END AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
  JOIN c ON (c.id_class = mtm.id_class);
1 голос
/ 23 октября 2008

Это не имеет смысла. Запрос типа:

SELECT * FROM relAC RAC
  INNER JOIN tableA A ON A.id_class = RAC.id_class 
  INNER JOIN tableC C ON C.id_class = RAC.id_class 
    WHERE A.id_class = B.id_class

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

0 голосов
/ 23 октября 2008

Лично я никогда не слышал от клиента требования, которое звучало бы так:

Получить информацию из таблицы B внутреннее соединение с A и C, и в тот же запрос относится к А и С в отношения один-много

Похоже, это то, к чему вы перевели требование. Не могли бы вы указать требование на простом английском языке, какие результаты хочет получить ваш клиент?

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