Это основано на вопросе Получить список списков в одном SQL утверждении - Я нашел решение, но у меня есть сомнения в его эффективности.
Переформулируем проблема:
- у нас есть 2 таблицы:
Person
и Parent
Person
содержит основы c данные о каждом человеке Parent
это объединяющая таблица, связывающая человека с его родителями - у каждого человека может быть несколько родителей
- мы хотим получать данные о каждом человеке со списком всех их предков - каждого предка в своем собственном ряду
- если нет предков, у нас есть только одна строка для этого человека с нулевым parentId
Вот формат данных:
Таблица персон
Id <PK>
Name
Родительская таблица
Id<PK>
ParentPersonId <FK into Person >
У человека есть строки со значениями PK
1, 'Jim'
2, 'John'
3, 'Anna'
4, 'Peter'
У родителя есть строки со значениями
1, 2
1, 3
2, 3
3, 4
Таким образом, у человека 1 есть предки 2 , 3, 4
Я хочу вывод в следующем виде
id name parentPersonId
--------------------------
1 Jim 2
1 Jim 3
1 Jim 4
2 John 3
2 John 4
3 Anna 4
4 Peter (null)
В моем решении используется рекурсивный CTE запрос, но я боюсь, что он производит слишком много строк, так как каждое поддерево может быть введено несколько раз. Мне нужно было отфильтровать дубликаты с различными данными, и план выполнения показывает, что даже с этими простыми данными сортировка по различным занимает 50% времени. Вот мой запрос:
WITH cte_org AS
(
SELECT per.id, per.name, par.parentPersonId
FROM Person per
LEFT JOIN Parent par ON per.id = par.id
UNION ALL
SELECT o.id, o.name, rec.parentPersonId
FROM Parent rec
INNER JOIN cte_org o ON o.parentPersonId = rec.id
WHERE rec.parentPersonId IS NOT NULL
)
SELECT DISTINCT *
FROM cte_org
ORDER BY id, parentPersonId;
http://sqlfiddle.com/#! 18 / d7d62 / 4
Мои вопросы:
- могу ли я каким-то образом обрезать уже посещенные ветви, чтобы рекурсивный CTE не создавал дублирующихся строк, и окончательное различение не требуется
- является ли рекурсивный CTE правильным подходом к этой проблеме?