Что лучший способ состоит в том, чтобы представить many-many отношения между записями в единственной таблице SQL?

По умолчанию Сканер использует «» в качестве разделителя. Вы ожидаете, что sc.next() вернет полную строку. Поэтому вам нужно установить EOL в качестве разделителя:

sc.useDelimiter(System.getProperty("line.separator"));

Это может помочь поместить выходные данные sc.next () в строковую переменную и распечатать ее, чтобы проверить, возвращает ли она то, что вы ожидаете:

[ 111]
6
задан Jonathan Leffler 24 January 2009 в 02:54
поделиться

8 ответов

Определите ограничение: entity_id_a < entity_id_b.

Создайте индексы:

CREATE UNIQUE INDEX ix_a_b ON entity_entity(entity_id_a, entity_id_b);
CREATE INDEX ix_b ON entity_entity(entity_id_b);

Второй индекс не должен включать entity_id_a поскольку Вы будете использовать его только для выбора всех aв одном b. RANGE SCAN на ix_b будет быстрее, чем a SKIP SCAN на ix_a_b.

Заполните таблицу со своими объектами следующим образом:

INSERT
INTO entity_entity (entity_id_a, entity_id_b)
VALUES (LEAST(@id1, @id2), GREATEST(@id1, @id2))

Затем выбор:

SELECT entity_id_b
FROM entity_entity
WHERE entity_id_a = @id
UNION ALL
SELECT entity_id_a
FROM entity_entity
WHERE entity_id_b = @id

UNION ALL здесь позволяет Вам использовать выше индексов и избежать дополнительной сортировки для уникальности.

Все выше допустимы для симметричных и антирефлексивных отношений. Это означает что:

  • Если связанного с b, то b связан с a

  • никогда не имел отношение к a

11
ответ дан 8 December 2019 в 18:42
поделиться

Я думаю структура, которую Вы предложили, прекрасен.

Для получения связанных записей делают что-то как

SELECT related.* FROM entities AS search 
LEFT JOIN entity_entity map ON map.entity_id_a = search.id
LEFT JOIN entities AS related ON map.entity_id_b = related.id
WHERE search.name = 'Search term'

Надежда, которая помогает.

1
ответ дан 8 December 2019 в 18:42
поделиться

Подход таблицы ссылки кажется прекрасным, за исключением того, что Вы могли бы хотеть 'тип связей' так, чтобы Вы знали, ПОЧЕМУ они связаны.

Например, отношение между Роли и Северной Каролиной не является тем же как отношением между Роли и Даремом. Кроме того, можно хотеть знать, кто 'родитель' в отношениях, в случае, если Вы управляли условным выражением, выпадает. (т.е. Вы выбираете состояние, Вы добираетесь для наблюдения городов, которые находятся в состоянии).

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

1
ответ дан 8 December 2019 в 18:42
поделиться

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

Если объекты находятся в (неналожении) классов эквивалентности, Вы могли бы хотеть сделать классы эквивалентности основанием для дизайна таблицы, где все в классе считают эквивалентным. Сами классы могут быть анонимными:

CREATE TABLE equivalence_class (
    class_id int -- surrogate, IDENTITY, autonumber, etc.
    ,entity_id int
)

entity_id должно быть уникальным для неперекрывающегося раздела Вашего пространства.

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

Затем Ваш запрос немного отличается:

SELECT c2.entity_id
FROM equivalence_class c1
INNER JOIN equivalence_class c2
    ON c1.entity_id = @entity_id
    AND c1.class_id = c2.class_id
    AND c2.entity_id <> @entity_id

или, эквивалентно:

SELECT c2.entity_id
FROM equivalence_class c1
INNER JOIN equivalence_class c2
    ON c1.entity_id = @entity_id
    AND c1.class_id = c2.class_id
    AND c2.entity_id <> c1.entity_id
1
ответ дан 8 December 2019 в 18:42
поделиться

Я могу думать о нескольких путях.

Единственная передача со СЛУЧАЕМ:

SELECT DISTINCT
    CASE
        WHEN entity_id_a <> @entity_id THEN entity_id_a
        WHEN entity_id_b <> @entity_id THEN entity_id_b
    END AS equivalent_entity
FROM entity_entity
WHERE entity_id_a = @entity_id OR entity_id_b = @entity_id

Или два фильтрованных запроса UNIONed таким образом:

SELECT entity_id_b AS equivalent_entity
FROM entity_entity
WHERE entity_id_a = @entity_id
UNION
SELECT entity_id_a AS equivalent_entity
FROM entity_entity
WHERE entity_id_b = @entity_id
0
ответ дан 8 December 2019 в 18:42
поделиться
select * from entities
where entity_id in 
(
    select entity_id_b 
    from entity_entity 
    where entity_id_a = @lookup_value
)
0
ответ дан 8 December 2019 в 18:42
поделиться

На основе Вашей обновленной схемы должен работать этот запрос:

select if(entity_id_a=:entity_id,entity_id_b,entity_id_a) as related_entity_id where :entity_id in (entity_id_a, entity_id_b)

где: entity_id связывается с объектом, который Вы запрашиваете

0
ответ дан 8 December 2019 в 18:42
поделиться

Мой совет состоит в том, что Ваш начальный дизайн таблицы плох. Не храните различные типы вещей в той же таблице. (Первое правило проектирования баз данных, право там с не хранит несколько сведений в том же поле). Это намного более трудно запросить и вызовет значительные проблемы производительности в будущем. Плюс он была бы проблема вводящий данные в таблицу отношений - как Вы знаете, какие объекты должны были бы быть связаны, когда Вы делаете новую запись? Было бы намного лучше разработать правильно реляционные таблицы. Таблицы объекта являются почти всегда плохой идеей. Я не вижу оснований вообще от примера, чтобы иметь этот тип информации в одной таблице. Откровенно у меня были бы университетская таблица и связанная таблица адресов. Это было бы легкий запросить и работать намного лучше.

-1
ответ дан 8 December 2019 в 18:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: