2012-08-24 41 views
9

Trong máy chủ SQLTSQL - Trong khi vòng lặp trong phạm vi được chọn?

Ok, vì vậy tôi đang làm việc với một bảng cơ sở dữ liệu trong đó các hàng có thể có hàng cha, sau đó có thể có hàng cha mẹ của riêng chúng. Tôi cần chọn 'hàng' gốc. Tôi không biết cách tốt nhất để làm điều này.

Có một trường có tên ParentId, liên kết hàng với hàng có ID đó. Khi ParentId = 0, nó là hàng gốc.

Đây là câu hỏi của tôi bây giờ:

SELECT Releases.Name,WorkLog.WorkLogId 

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

Tôi không thực sự cần Name phát hành của phiên bản trẻ, tôi muốn chỉ gốc phát hành Tên, vì vậy tôi muốn chọn kết quả của vòng lặp while như sau:

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

Select Release.Name 
where Release.RealeaseId = @ReleaseId 

Tôi biết cú pháp đó thật kinh khủng, nhưng hy vọng tôi sẽ cho bạn ý tưởng về những gì tôi đang cố gắng đạt được.

+1

Vì vậy, tôi đoán có nhiều hơn một phiên bản với 'ParentReleaseId' bằng số không? – AakashM

+0

Bạn có nói rằng bảng Bản phát hành có phân cấp không, ví dụ: Bản phát hành X có phiên bản tiền nhiệm và sau đó bản phát hành đó có người tiền nhiệm của riêng nó, v.v. Vì vậy, vấn đề là tìm bản phát hành * gốc * cho bất kỳ bản phát hành * sau * nào xảy ra trong các ngày được chỉ định? –

+0

Hy vọng rằng, bạn vào năm 2005 hoặc mới hơn - bạn có thể xác nhận không? –

Trả lời

9

Dưới đây là một ví dụ, mà có thể là hữu ích:

Truy vấn này là nhận được một yếu tố thấp hơn của một cái cây, và tìm đến cha mẹ của cha mẹ. Giống như tôi có 4 cấp độ trong bảng của tôi -> loại 7-> 5, 5-> 3, 3-> 1. Nếu tôi đưa nó cho 5 nó sẽ tìm thấy 1, bởi vì đây là cấp cao nhất trong ba.

(Thay đổi lựa chọn bạn có thể có tất cả các bậc cha mẹ lên trên con đường cuối cùng.)

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, hãy đánh tôi với CTE. Làm tốt lắm :) –

+0

Cảm ơn, tôi đang sử dụng 'các thuật toán' này rất nhiều trong tuần này :) –

+0

Điều này có hiệu quả với số lượng không giới hạn không? –

1

một cái gì đó như thế này

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 

và với fiddle: http://sqlfiddle.com/#!3/a5fa1/1/0

+0

Tôi nghĩ rằng các thành viên neo của CTE sẽ phải đối phó với những hạn chế ngày của truy vấn ví dụ của OP, phải không? –

+0

Từ những gì tôi hiểu giá trị bắt đầu được chọn trước đó, và ràng buộc ngày tháng sẽ được chọn. –

0

Sử dụng Andras cách tiếp cận, tôi đã chỉnh sửa lựa chọn cuối cùng để trực tiếp cung cấp cho tôi ID của bản phát hành gốc

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 

Vấn đề của tôi là bây giờ tôi muốn chạy qua tất cả @IDs (905 trong mã đó) và tham gia mỗi bản ghi đến một kết quả

Các vấn đề liên quan