2013-02-14 3 views
2

Я пытаюсь представить следующую рекурсивную связь в РСУБД:рекурсивный объект ж/из родителя/ребенка отношения

enter image description here

В качестве основного примера, мы имеем следующие поля:

1 - computer science 
2 - computer engineering 
3 - electrical engineering 
4 - mathematics 

И я хочу связать похожие поля друг с другом. Я мог бы использовать вторую таблицу, чтобы связывать поля друг с другом. Оптимально, я мог себе представить, что в таком виде:

+----------+----------+ 
| field1 | field2 | 
+----------+----------+ 
| 4  | 1  | (math -> comp sci) 
| 4  | 2  | (math -> comp eng) 
| 4  | 3  | (math -> elect eng) 
| 2  | 1  | (comp eng -> comp sci) 
| 2  | 3  | (comp eng -> elect eng) 
+----------+----------+ 

Однако, если ключ был (field1, field2), я вижу две потенциальные проблемы:

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

Например:

+----------+----------+ 
| field1 | field2 | 
+----------+----------+ 
| 1  | 4  | (comp sci -> math) 
| 4  | 3  | (math -> elect eng) 
| 4  | 2  | (math -> comp eng) 
| 3  | 4  | (elect eng -> math) 
| 2  | 1  | (comp eng -> comp sci) 
| 3  | 2  | (elect eng -> comp eng) 
| 1  | 2  | (comp sci -> comp eng) 
+----------+----------+ 

Как я должен подойти неиерархические рекурсивные отношения?

Должен ли я идти и намеренно дублировать каждый кортеж, как во второй таблице? Или есть другой метод, который я пересматриваю?

ответ

1

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

Используя ваш пример выше, другой подход заключается в представлении таблицы SimilarField. Он будет хранить SimilarId и FieldId (и некоторые люди будут утверждать третье поле Identity, SimilarFieldId). Так что, если английский язык и литература были подобные поля, то вы могли бы:

SimilarId FieldId 
1   1   (English) 
1   2   (Literature) 

Такой подход позволяет иметь 1-н связь между вашими полями и их подобными полями.

--EDIT--

В ответ на ваш комментарий, не знаю, как ваш пример не работает:

SimilarId FieldId 
1   1   (English) 
1   2   (Literature) 
1   3   (Reading) 
2   2   (Literature) 
2   4   (History) 
3   4   (History) 
3   5   (Art History) 

Вы можете иметь столько сгруппированных подобные поля, как это необходимо.

Чтобы получить все поля, связанные с литературой, например, запрос может выглядеть следующим образом:

SELECT DISTINCT F.FieldId, F.FieldName 
FROM Field F JOIN 
     SimilarField S ON F.FieldId = S.FieldId 
WHERE S.SimilarId IN (
     SELECT SimilarId 
     FROM SimilarField 
     WHERE FieldId = 2 
    ) 

А вот пример SQL Fiddle.

+0

Я могу быть смущен (все же), но я думаю, что мне нужно много-ко-многим, и ваш пример позволил бы Литературе иметь одно подобное поле. * (Я обновил пример в своем вопросе) * –

+0

@DavidKaczynski - Я уверен, что используя этот подход, вы можете связать N-N в этом отношении, но отношение 1-N в подобных группах. См. Правки выше. – sgeddes

+0

Спасибо за разъяснение. Пожалуйста, позвольте мне спросить об этом: если я хочу получить все поля, похожие на чтение, как будет выглядеть этот запрос? например, 'select SimilarId, FieldId from SimilarField, где SimilarId = 3 или FieldId = 3' ..., но как я могу превратить полученные кортежи' (SimilarId, FieldId) в набор отдельных идентификаторов для запроса исходной таблицы поля ? –

1

Один общий подход к проблеме дублирования состоит в том, чтобы убедиться, что field1 всегда содержит самый низкий идентификатор в кортеже, в сочетании с ключом UNIQUE на обоих столбцах. Тогда ваше состояние для SELECT может быть только WHERE field1 = @id OR field2 = @id.

Смежные вопросы