Рекурсивный запрос в MySQL для определения типа наследования

#mysql #sql #hierarchical-data #recursive-query

#mysql #sql #иерархический-данные #рекурсивный запрос

Вопрос:

У меня есть таблица с информацией о переменных типах данных. Вызываемая inheritance таблица со столбцами derived и base и следующими образцами данных;

 derived | base

 Double | Number
 Int    | Number
 Int64  | Int
 Number | Object
  

Как видно, могут быть некоторые базовые типы данных, которые также принадлежат производному столбцу. Но гарантируется отсутствие циклических зависимостей. Моя цель — получить выходные данные в виде двух столбцов, derived , и base где base столбец является конечным корневым базовым элементом для соответствующего производного типа.

Например, Int64 имеет базовое значение as Int . Я пытаюсь использовать рекурсию с версией MySQL> 8.0. Вот моя попытка;

 WITH RECURSIVE hierarchy AS (
SELECT 
derived,
base 
 
FROM inheritance 

UNION ALL

SELECT

inheritance.derived,
inheritance.base
FROM inheritance,hierarchy
WHERE inheritance.derived = hierarchy.base)

SELECT *
FROM hierarchy;
  

Кажется, что в моем завершении есть ошибка, поэтому я получаю следующую ошибку;

ERROR 3636 (HY000) at line 715: Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value. .

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

Комментарии:

1. Я проверил то, что вы показали, но я не получаю никакой ошибки. Я использую MySQL 8.0.21. Какую точную версию вы используете?

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

3. Пожалуйста, предоставьте примеры данных и желаемые результаты.

Ответ №1:

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

Затем вы, похоже, хотите:

 with recursive hierarchy as (
    select derived, base, 1 lvl from inheritance
    union all
    select h.derived, i.base, h.lvl   1
    from hierarchy h
    inner join inheritance i on i.derived = h.base
)
select derived, base
from hierarchy h
where lvl = (select max(h1.lvl) from hierarchy h1 where h1.derived = h.derived)
  

Обоснование:

  • вы хотите отслеживать оригинал derived по мере продвижения вверх по иерархии

  • рекурсивный запрос генерирует одну строку на промежуточный уровень; во внешнем запросе требуется дополнительная логика, чтобы сохранить только «самый глубокий» родительский элемент

Демонстрация в DB Fiddle как с вашим исходным запросом, так и с новым запросом

Комментарии:

1. @GMB ценю ваш ответ. Это имеет смысл. Мне было интересно, если я хочу изменить только для тех строк, где есть base Number , могу ли я просто фильтровать во внешнем запросе, а не брать самый глубокий уровень. Не могли бы вы любезно подтвердить?