У меня есть набор данных из таблицы (TableA
), который относится к себе через TableB
. У родителей в TableA
есть дети в TableA
. У этих детей тоже могут быть дети. Ничего удивительного здесь.
У меня есть набор строк верхнего уровня из TableA
, с которыми мне нужно работать. Прежде чем я смогу работать с этими строками, я должен иметь под рукой каждый дочерний ряд. Я должен иметь возможность работать с каждой строкой верхнего уровня TableA
(и это дети) как можно быстрее в моем приложении.
Я не могу найти способ сделать это.
Использование рекурсивного CTE (TableA
верхнего уровня, установленного как якорь, TableB->TableA
join как объединение), не удовлетворяет требованиям. Весь набор верхнего уровня от TableA
возвращается в CTE до того, как он работает на уровне 2 дочерних элементов. Затем он работает на уровне 3. Затем на уровне 4 и т. Д. Поскольку мой набор верхнего уровня составляет около 400 000 и более строк, мое клиентское приложение не может начать работать со строками, пока на сервере не будет упакован ВЕСЬ набор данных.
Мне нужен лучший способ сделать это. Я попытался передать клиенту плоский набор строк TableA
верхнего уровня и заставить клиента неоднократно выдавать рекурсивный оператор CTE для каждой строки TableA
верхнего уровня. Это на самом деле работает. Но слишком много шума. Устойчивая скорость поиска строк слишком велика из-за многократного переиздания операторов.
Мне нужно креативное решение.
Фрагмент CTE для каждой записи, который я использую. В этом примере TableA - это Member, а TableB - это MemberReplace. Я вырвал большую часть оператора select в середине и большую часть соединений.
WITH T_MemberRecurse
(
MemberId,
IncludedMemberId,
Level
) AS (
SELECT Member.Id,
Member.Id,
0
FROM MemberInput
INNER JOIN MemberInputItem
ON MemberInputItem.MemberInputId = MemberInput.Id
INNER JOIN Member
ON Member.Id = MemberInputItem.MemberId
UNION ALL
SELECT T_MemberRecurse.MemberId,
Member2.Id,
Level + 1
FROM T_MemberRecurse
INNER JOIN Member
ON Member.Id = T_MemberRecurse.IncludedMemberId
INNER JOIN MemberReplacement
ON MemberReplacement.MemberId = Member.Id
INNER JOIN Member Member2
ON Member2.Id = MemberReplacement.OriginalMemberId
)
SELECT Member.Id,
T_MemberRecurse.IncludedMemberId,
T_MemberRecurse.Level,
FROM MemberInput
INNER JOIN LotsOfTables