2010-10-14 11 views
6

Najpierw muszę przyznać, że nie jestem zaznajomiony z serwerem sql recursive CTE's, ale uważam, że jest to najlepsze podejście.Rekurencyjne CTE do wyszukiwania rekordów nadrzędnych

Mam tabelę tabData. Jego PK nosi nazwę idData i jest to samo-odwołanie do FK fiData.

Schema

Więc fiData odwołuje się do rekordu nadrzędnego i SELECT * FROM tabData WHERE idData=fiData przywrócenie wszystkich danych jednostki dominującej. Jest to proste i szybkie. Ale jak zdobyć wszystkich rodziców z danego rekordu w naturalnym porządku? Say jest jedno dziecko (idData = 4) z 3 rodzicami (pierwszy rodzic jest zapis z idData = 3):

idData fiData 
4   3  
3   2  
2   1  
1   NULL  

Myślałem rekurencyjne CTE jest do zrobienia, ale nie dogadać dobrze ze swoją składnią. Jaki jest zatem właściwy sposób wdrożenia CTE, który zwraca wszystkich rodziców?

Próbowałem następujących, ale daje mi zły wynik (3,4 zamiast 3,2,1): (przetestować go i stworzył tabeli tymczasowej dla mnie i Ciebie)

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]; 

Z góry dziękuję.

Odpowiedz

7

Zmiana na:

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

dał mi wyniki chciałeś.

+2

Dzięki, było bardzo blisko;) –

6

Masz połączenie do tyłu.

Zmiana ta

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

do tego

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

Dzięki Kirk Woll był kilka sekund szybciej. –

Powiązane problemy