Получить строки по транзитивности в MySQL

Предположим, у меня есть следующая таблица:

Images

|id | similarTo|
|---|----------|
|1  |  2       |
|2  |  3       |
|--------------|

Где SimilarTo - это внешний ключ к идентификатору. То, что я хочу, это запрос, который может получить транзитивное закрытие идентификатора до 2 уровней в обоих направлениях. Другими словами, мы имеем: A -> B ---> C, а также C -> B -> A

И поэтому в этом случае я хотел бы вернуть:

Given 1: 2,3
Given 2: 1,3
Given 3: 1,2

По сути, я храню функцию (изображение A) аналогично (изображение B) в таблице. Эта функция работает в обоих направлениях, поэтому, если A похож на B, то B похож на A. Теперь мне нужен запрос, который может найти все изображения, похожие на данное изображение, до двух уровней / шагов... (то есть, если учитывая A -> B -> C -> D, теперь, если я хочу найти все изображения, похожие на A, он вернул бы B,C)

1 ответ

Решение

Может быть запрос, как показано ниже:

SELECT 
id,
similarTo
From images

UNION ALL

SELECT 
t1.id,
t2.similarTo
FROM images t1
INNER JOIN images t2 ON t1.similarTo = t2.id AND t1.id < t2.id

DEMO

Второй запрос фактически порождает transitive связь. И первый получает все определенные отношения в вашей таблице.

Выход:

Вы получите вывод, как показано ниже:

| id | similarTo |
|----|-----------|
|  1 |         2 |
|  2 |         3 |
|  1 |         3 |

РЕДАКТИРОВАТЬ:

Для конкретных id сказать id=2:

SELECT 
id,
similarTo
From images
WHERE id=2 or similarTo=2

UNION ALL

SELECT 
t1.id,
t2.similarTo
FROM images t1
INNER JOIN images t2 ON t1.similarTo=2 AND t2.id =2 AND t1.id < t2.id

DEMO

Другие вопросы по тегам