2012-08-24 17 views
9

W serwerze SQLTSQL - Podczas gdy pętla w select?

Ok, więc pracuję z tabelą bazy danych, w której wiersze mogą mieć nadrzędne wiersze, które mogą mieć własne wiersze nadrzędne. Muszę wybrać główny "wiersz". Nie wiem, jak to zrobić najlepiej.

Istnieje pole o nazwie ParentId, które łączy wiersz z wierszem o tym identyfikatorze. Kiedy ParentId = 0, jest to wiersz główny.

To moje zapytanie teraz:

SELECT Releases.Name,WorkLog.WorkLogId 

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

I naprawdę nie trzeba nazwie wydania z wydawnictw dziecięcych, chcę tylko korzeń Nazwa Release, więc chcę, aby wybrać wynik pętli while tak:

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

Select Release.Name 
where Release.RealeaseId = @ReleaseId 

wiem, że składnia jest straszne, ale miejmy nadzieję, że daję ci pomysł co usiłuję acheive.

+1

Więc zgaduję istnieje więcej niż jeden uwolnienie się od 'ParentReleaseId' równa zero? – AakashM

+0

Czy mówisz, że tabela Uwolnienia jest hierarchiczna, np. Release X ma poprzednika, a następnie to wydanie ma swój poprzednik i tak dalej? Tak więc problemem jest znalezienie * oryginalnej * wersji dla dowolnego * późniejszego * wydania występującego w określonych datach? –

+0

Mam nadzieję, że jesteś w 2005 lub później - czy możesz potwierdzić? –

Odpowiedz

9

Oto przykład, który może być przydatny:

To zapytanie jest coraz niższy element drzewa i szukają do rodzica rodziców. Tak jak mam 4 poziomy w moim stole -> kategoria 7-> 5, 5-> 3, 3-> 1. Jeśli dam to 5 to znajdzie 1, ponieważ jest to najwyższy poziom z trzech.

(Zmiana ostatnią wybrać można mieć wszystko od rodziców po drodze.)

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, pokonaj mnie za pomocą CTE. Dobra robota :) –

+0

Dzięki, używam tych "algorytmów" dużo w tym tygodniu :) –

+0

Czy to działa na nieskończoną liczbę poziomów? –

1

coś takiego

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 

i skrzypce: http://sqlfiddle.com/#!3/a5fa1/1/0

+0

Myślę, że element zakotwiczający CTE będzie musiał poradzić sobie z ograniczeniami daty w przykładowej kwerencji OP, prawda? –

+0

Z tego co rozumiem, wartość początkowa jest wybierana wcześniej, a ograniczenie dotyczące daty będzie dotyczyć tego wyboru. –

0

Korzystanie Andras podejście, edytowałem ostateczny wybór, aby bezpośrednio podać identyfikator głównego wydania

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 

Mój problem jest teraz chcę uruchomić przez wszystkie @IDs (905 w tym kodzie) i dołączyć każdy rekord do wyniku

Powiązane problemy