Рекурсивная выборка из MariaDB всех связей

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

Моя таблица:

CREATE TABLE `mytable` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `x` int(11) NOT NULL,
  KEY `a` (`a`,`b`,`x`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `mytable` (`a`, `b`, `x`) VALUES
(1, 1, 1),
(2, 1, 1),
(2, 2, 5),
(3, 2, 2),
(3, 2, 4),
(3, 3, 2),
(4, 3, 2),
(4, 3, 3),
(5, 3, 4),
(6, 3, 4);

Моя задача получить все связи строк используя то поле X то поля A и B.

Сначала находим все записи с условием a = 4 b = 3 затем ищем все записи совпадающие с X и у найденных записей ищем уже с новыми условиями и так рекурсивно.

Я использовал следующий запрос, но получаю бесконечную рекурсию и понимаю почему так происходит, но не понимаю что необходимо добавить дабы остановить бесконечную рекурсию. Я пробовал использовать LIMIT но это не даёт никакого эффекта, полагаю я копаю не в ту сторону.

WITH RECURSIVE cte (a, b, x) as (
    SELECT      a, b, x
    FROM        mytable
    WHERE       a = 4 AND b = 3
    UNION ALL
    SELECT      m.a, m.b, m.x
    FROM        mytable m
    INNER JOIN  cte ON m.x = cte.x
)
SELECT * FROM cte;

Небольшой визуальный фрагмент связей


Ответы (1 шт):

Автор решения: Akina

Для исключения бесконечной рекурсии следует использовать UNION DISTINCT.

Поскольку требуется на нечётном шаге связывать по x, а на чётном по (a, b) - используются два рекурсивных блока.

WITH RECURSIVE
cte AS (
  SELECT a, b, x FROM test WHERE (a, b) = (4, 3)
  UNION 
  SELECT test.a, test.b, x FROM test JOIN cte USING (x)  
  UNION 
  SELECT a, b, test.x FROM test JOIN cte USING (a, b)
)
SELECT * FROM cte ORDER BY a, b, x

fiddle

PS. Есть такая шутка: "Чтобы понять, как выполняется рекурсия, надо понять, как выполняется рекурсия". Однако в данном случае и в приведённой формулировке это не шутка, а чёткая и совершенно однозначная инструкция.

→ Ссылка