2010-10-14 22 views
6

primero debo admitir que no estoy muy familiarizado con el servidor sql recursive CTE's pero creo que este es el mejor enfoque.CTE recursivo para buscar registros principales

Tengo una mesa tabData. Su PK se llama idData y hay una referencia automática FK fiData.

Schema

Así fiData hace referencia al registro padre y SELECT * FROM tabData WHERE idData=fiData devuelve todos los datos de la matriz. Esto es simple y rápido. Pero, ¿cómo conseguir que todos los padres de un registro dado en el orden natural? Digamos que hay un niño (idData = 4) con 3 padres (primer padre es el registro con idData = 3):

idData fiData 
4   3  
3   2  
2   1  
1   NULL  

pensé CTE recursiva es el camino a seguir, pero no se llevan bien con su sintaxis Entonces, ¿cuál es la forma correcta de implementar el CTE que devuelve a todos los padres?

me trataron siguiente, pero me da un resultado erróneo (3,4 en lugar de 3,2,1): (Para probar que he creado una tabla temporal para mí y usted)

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

Gracias de antemano.

Respuesta

7

Cambiar a:

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

me dio los resultados que quería.

+2

Gracias, yo estaba muy cerca;) Gracias –

6

Tiene la unión hacia atrás.

Cambie este

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

a este

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

, Kirk Woll fue unos segundos más rápido. –

Cuestiones relacionadas