несколько минут назад я спросил здесь , как получить родительские записи с рекурсивным CTE.Это работает сейчас, но я получаю неправильный порядок (в обратном порядке, упорядоченный PK idData), когда я создаю табличную функцию, которая возвращает всех родителей.Я не могу заказать напрямую, потому что мне нужен логический порядок, предоставленный CTE.
Это дает правильный порядок (от следующего родителя к этому родителю и т. Д.):
declare @fiData int;
set @fiData=16177344;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
select iddata from PreviousClaims
Но следующееФункция возвращает все записи в обратном порядке (упорядочено по PK):
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
AS
BEGIN
DECLARE @idData int;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
INSERT INTO @retPreviousClaims
SELECT idData FROM PreviousClaims;
RETURN;
END;
select * from dbo._previousClaimsByFiData(16177344);
ОБНОВЛЕНИЕ: Поскольку все считают, что CTE не упорядочивает ( Любой "упорядочивание")будет совершенно произвольным и случайным ), я задаюсь вопросом, почему противоположное кажется верным.Я запросил заявку на ребенка со многими родителями, и порядок в CTE - это вполне логичный порядок, когда я перехожу от ребенка к родителю и так далее.Это будет означать, что CTE выполняет итерацию от записи к записи, как курсор, и следующий выбор возвращает его точно в этом порядке.Но когда я позвонил в TVF, я получил порядок первичного ключа idData.
Решение было простым.Мне нужно было только удалить родительский ключ таблицы возврата TVF.Так что измените ...
RETURNS @retPreviousClaims TABLE
(
idData int PRIMARY KEY NOT NULL
)
на ...
RETURNS @retPreviousClaims TABLE
(
idData int
)
.. и он сохранит правильный «порядок» (в том же порядке, в котором они были вставлены во временный набор результатов CTE).
ОБНОВЛЕНИЕ2: Поскольку Дэмиен упомянул, что «порядок CTE» может измениться при определенных обстоятельствах, я добавлю новый столбец relationLevel
в CTE, который описывает уровень взаимосвязиродительские записи (что, кстати, в общем случае полезно для куба ssas).Итак, окончательный Inline-TVF (который возвращает все столбцы) теперь:
CREATE FUNCTION [dbo].[_previousClaimsByFiData] (
@fiData INT
)
RETURNS TABLE AS
RETURN(
WITH PreviousClaims
AS(
SELECT 1 AS relationLevel, child.*
FROM tabData child
WHERE child.idData = @fiData
UNION ALL
SELECT relationLevel+1, child.*
FROM tabData child
INNER JOIN PreviousClaims parent ON parent.fiData = child.idData
)
SELECT TOP 100 PERCENT * FROM PreviousClaims order by relationLevel
)
Это примерное соотношение:
select idData,fiData,relationLevel from dbo._previousClaimsByFiData(46600314);
Спасибо.