2010-10-14 2 views
6

Сначала я должен признать, что я не очень хорошо знаком с recursive CTE's сервера sql, но я думаю, что это лучший подход.Рекурсивный CTE, чтобы найти родительские записи

У меня есть таблица tabData. Его PK называется idData, и есть саморегулятор FK fiData.

Schema

Так fiData ссылается на родительскую запись и SELECT * FROM tabData WHERE idData=fiData возвращает все данные материнской. Это просто и быстро. Но как получить всех родителей от данной записи в натуральном порядке? Скажет есть один ребенок (idData = 4) с 3-мя родитель (первый родителем является записью с idData = 3):

idData fiData 
4   3  
3   2  
2   1  
1   NULL  

Я думал, что рекурсивный КТР путь, но я не лажу хорошо с его синтаксисом. Итак, каков правильный способ реализации CTE, который возвращает всех родителей?

Я попытался следующие, но это дает мне неправильный результат (3,4 вместо 3,2,1): (Для того, чтобы проверить это я создал временную таблицу для меня и вас)

IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'tabData_Temp')) 
BEGIN 
CREATE TABLE [dbo].[tabData_Temp](
    [idData] [int] NOT NULL, 
    [fiData] [int] NULL, 
    CONSTRAINT [PK_tabData_Temp] PRIMARY KEY CLUSTERED 
    (
    [idData] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
); 

ALTER TABLE [dbo].[tabData_Temp] WITH CHECK ADD CONSTRAINT [FK_tabData_Temp] FOREIGN KEY([fiData]) 
REFERENCES [dbo].[tabData_Temp] ([idData]); 
ALTER TABLE [dbo].[tabData_Temp] CHECK CONSTRAINT [FK_tabData_Temp]; 

INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(1,NULL); 
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(2,1); 
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(3,2); 
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(4,3); 
END 

/* here comes the (not working) recursive CTE */ 
Declare @fiData int; 
SET @fiData = 3; 
WITH PreviousClaims(idData,fiData) 
AS(
    SELECT parent.idData,parent.fiData 
    FROM tabData_temp parent 
    WHERE parent.idData = @fiData 

    UNION ALL 

    SELECT child.idData,child.fiData 
    FROM tabData_temp child 
    INNER JOIN PreviousClaims parent ON parent.idData = child.fiData 
) 
SELECT idData 
FROM PreviousClaims; 
/* end of recursive CTE */ 


DROP TABLE [dbo].[tabData_Temp]; 

Заранее спасибо.

ответ

7

Переход к:

INNER JOIN PreviousClaims parent ON parent.fiData = child.idData 

дал мне результаты, которые вы хотели.

+2

Спасибо, я был очень близок;) –

6

У вас есть соединение назад.

Изменить этот

INNER JOIN PreviousClaims parent ON parent.idData= child.fiData 

к этому

INNER JOIN PreviousClaims parent ON parent.fiData = child.idData 
+0

Спасибо, Кирк Волл был несколько секунд быстрее. –

Смежные вопросы