2012-08-24 31 views
9

En el servidor SQLTSQL - ¿Mientras se realiza el ciclo dentro de seleccionar?

Ok, entonces estoy trabajando con una tabla de base de datos en la que las filas pueden tener filas primarias, que pueden tener sus propias filas padre. Necesito seleccionar la raíz 'fila'. No sé la mejor manera de hacer esto.

Hay un campo llamado parentid, que une a la fila a la fila con ese ID. Cuando ParentId = 0, es la fila raíz.

Esta es mi consulta ahora:

SELECT Releases.Name,WorkLog.WorkLogId 

FROM WorkLog,Releases 
WHERE 
Releases.ReleaseId = WorkLog.ReleaseId 
and WorkLogDateTime >= @StartDate 
and WorkLogDateTime <= @end 

que realmente no necesita el Nombre de la revisión de las notas de niño, quiero solamente la raíz Nombre de la liberación, por lo que quiero para seleccionar el resultado de Mientras que un bucle como este:

WHILE (ParentReleaseId != 0) 
BEGIN 
@ReleaseId = ParentReleaseId 
END 

Select Release.Name 
where Release.RealeaseId = @ReleaseId 

sé que la sintaxis es horrible, pero espero que te estoy dando una idea de lo que estoy tratando de acheive.

+1

así que supongo que hay más de una versión con 'ParentReleaseId' igual a cero? – AakashM

+0

¿Está diciendo que la tabla de versiones es jerárquica, por ejemplo, la versión X tiene un predecesor y luego esa versión tiene su propio predecesor, y así sucesivamente? Entonces, ¿el problema es encontrar el lanzamiento * original * para cualquier lanzamiento * posterior * que ocurra dentro de las fechas especificadas? –

+0

Esperemos que estés en 2005 o después, ¿puedes confirmarlo? –

Respuesta

9

Aquí es un ejemplo, lo que podría ser útil:

Esta consulta es cada vez un elemento inferior de un árbol, y buscando hasta que el padre de los padres. Me gusta Tengo 4 niveles en mi tabla -> categoría 7-> 5, 5-> 3, 3-> 1. Si le doy el 5, encontrará el 1, porque este es el nivel superior de los tres.

(Cambiando el pasado seleccione puede tener todos los padres en el camino.)

DECLARE @ID int 

SET @ID = 5; 

WITH CTE_Table_1 
(
    ID, 
    Name, 
    ParentID 
) 
AS(
    SELECT 
    ID, 
    Name, 
    ParentID 
    FROM Table_1 
    WHERE ID = @ID 

UNION ALL 

SELECT 
    T.ID, 
    T.Name, 
    T.ParentID 
FROM Table_1 T 
INNER JOIN CTE_Table_1 ON CTE_Table_1.ParentID = T.ID 
) 

SELECT * FROM CTE_Table_1 WHERE ParentID = 0 
+0

DARN, golpéame con el CTE. Buen trabajo :) –

+0

Gracias, estoy usando estos 'algoritmos' mucho en esta semana :) –

+0

¿Esto funcionará para un número indefinido de niveles? –

1

algo como esto

with cte as 
(
    select id,parent_id from t where [email protected] 
    union all 
    select t.id,t.parent_id 
    from cte 
    join t on cte.parent_id = t.id where cte.parent_id<>0 
) 
select * 
from cte 
join t on cte.id=t.id where cte.parent_id = 0 

y con el violín: http://sqlfiddle.com/#!3/a5fa1/1/0

+0

Creo que el miembro ancla del CTE tendrá que lidiar con las restricciones de fecha de la consulta de ejemplo del PO, ¿no? –

+0

Por lo que entiendo, el valor inicial se seleccionó antes, y la restricción de fecha estará en esa selección. –

0

Usando Andras enfoque, he editado la final seleccione darme directamente el identificador de la liberación de la raíz

WITH cte_Releases 
( 
    ReleaseId, 
    ParentReleaseID 
) 
AS( 
    SELECT 
    ReleaseId, 
    ParentReleaseID 
    FROM Releases 
    Where ReleaseId = 905 

UNION ALL 

SELECT 
    R.ReleaseId, 
    R.ParentReleaseID 
FROM Releases R 
INNER JOIN cte_Releases ON cte_Releases.ParentReleaseID = R.ReleaseId 
) 

SELECT max(ReleaseId) as ReleaseId, min(ReleaseId) as RootReleaseId FROM cte_Releases 

Mi problema ahora es que quiero ejecutar a través de todos los @IDs (905 en ese código) y unirse a cada registro a un resultado

Cuestiones relacionadas