Двусторонние отношения в запросах SQL - PullRequest
7 голосов
/ 07 октября 2011

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

PartID (PK), int
PartNumber , Varchar (50), Unique
Описание , Varchar (255)

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

PartID , (PK), int
SecondPartID , (PK), int
ReasonForShoityity , Varchar (255)

Затем между двумя таблицами было установлено отношение многие ко многим.

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

Итак, как решить эту проблему?Может ли это быть решено только с помощью SQL, или нужно ли изменить мою конструкцию в соответствии с требованиями бизнеса?

Рассмотрим следующие части XYZ123, ABC123, ABC234, ABC345, ABC456 и EFG456, которые были введены в существующую введенную структурувыше.Вы можете получить данные, которые выглядят следующим образом (без поля причины, которое на данном этапе не имеет значения):

PartID , SecondPartID
XYZ123, ABC123
XYZ123, ABC234
XYZ123, ABC345
XYZ123, ABC456
EFG456, XYZ123

Мой пользователь хочет знать "Какие детали похожи на XYZ123" .Это можно сделать с помощью запроса, например, так:

SELECT SecondPartID
FROM tblRelatedParts
WHERE PartID = 'XYZ123'

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

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

@ Goran

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

Перечисленные выше данные заносятся в новую таблицу(Обратите внимание, что я изменил partID на номер детали, чтобы сделать пример более понятным; хотя семантика моей проблемы не изменилась)

Таблица будет выглядеть так:

RelationshipID , PartNumber
1, XYZ123
1, ABC123
2, XYZ123
2, ABC234
3, XYZ123
3, ABC345
4, XYZ123
4, ABC456
5, EFG456
5, XYZ123

Затем я могу получить список похожих деталей, используя такой запрос:

SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
                          FROM tblPartRelationships
                          WHERE PartNumber = 'XYZ123')

Я проведу еще несколько тестов, и если это сработает, я получу обратную связь иccept ответ.

Ответы [ 4 ]

7 голосов
/ 07 октября 2011

Я справился с этой проблемой, настроив таблицу отношений.

Таблица деталей:

PartID (PK), int

PartNumber , Varchar (50), уникальный

Описание , Varchar (255)

Таблица отношений Part:

RelationshipId (FK), int

PartID (FK), int

Таблица отношений:

RelationshipId (PK), int

Теперь похожие части просто добавляются в таблицу отношений:

RelationshipId, PartId

1,1

* * 1,2 одна тысяча тридцать восемь

Всякий раз, когда вы добавляете другую деталь с отношением ID = 1, она считается похожей на любую деталь с отношением IID = 1.

Возможные API-решения для добавления отношений:

  • Создать новые отношения для каждого списка похожих частей. Позвольте клиенту загружать, изменять и обновлять весь список, когда это необходимо.
  • Получите отношения для подобного объекта. Отфильтруйте список по некоторым критериям, чтобы остался только один, или разрешите клиенту выбирать из существующих отношений. При необходимости создайте, удалите запись PartRelationship.
  • Получить список отношений из таблицы отношений. Позвольте клиенту указать детали и отношения. При необходимости создайте, удалите записи PartRelationship.
2 голосов
/ 07 октября 2011

Добавить ограничение CHECK, например

CHECK (PartID < SecondPartID);
0 голосов
/ 16 января 2013

Как насчет двух строк для каждого сходства.Например, если у вас есть похожие объекты A, B, вы будете иметь их в своей таблице отношений

A B
B A

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

  • , вы не будете использовать союз.Союз кончился убийством в любых БДМ.Особенно, когда у вас есть порядок по или группа по
  • , вы можете реализовать более конкретное отношение: a связано с b, но b не связано с a.Например, Джон может заменить Дейва, но Дейв не может заменить Джона.
0 голосов
/ 02 апреля 2012

Я знаю, что это старый, но почему бы просто не выполнить этот запрос с вашей исходной схемой? Меньше таблиц и строк.

SELECT SecondPartID
FROM tblRelatedParts
WHERE PartID = 'XYZ123' 
UNION
SELECT PartID
FROM tblRelatedParts
WHERE SecondPartID = 'XYZ123'

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

...