2012-03-20 46 views
1

相關問題duplitace值最大遞歸錯誤:TSQL check if specific rows sequence existsTSQL遞歸 - 在表

我想諮詢一下遞歸的第二個問題,因爲這一次是不同的東西(在我看來),所以請不要刪除它。

我有一個包含表值:

ORDER_ID Previous_STATUS_ID Next_STATUS_ID Create_Date 
2   null     1    '2012-01-02' 
2   1     2    '2012-01-03' 
2   2     3    '2012-01-04' 
2   3     1    '2012-01-05' 
3   1     2    '2012-01-06' 
2   2     3    '2012-01-10' 
2   3     5    '2012-01-13' 
2   5     1    '2012-01-22' 
2   1     2    '2012-01-22' 

這工作得很好:

with change_tree as 
(
    SELECT order_id, 
     previous_status_id, 
     next_status_id, 
     cast(next_status_id as varchar(max)) as status_path 
    FROM status_change 
    WHERE previous_status_id = 5 
    AND order_id = 2 

    UNION ALL 

    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     ct.status_path + ',' + cast(sc.next_status_id as varchar(max)) 
    FROM status_change sc 
    JOIN change_tree ct ON ct.next_status_id = sc.previous_status_id AND ct.order_id = sc.order_id 
) 
SELECT * 
FROM change_tree 
WHERE status_path = '5,1'; 

但如果我修改它,像這樣:

with change_tree as 
(
    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     cast(sc.next_status_id as varchar(max)) as status_path, 
     sc.Create_Date as StartDate, 
     sc.Create_Date as EndDate 
    FROM status_change sc 
    WHERE previous_status_id = 1 
    AND order_id = 2 

    UNION ALL 

    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     ct.status_path + ',' + cast(sc.next_status_id as varchar(max)) 
     sc.Create_Date as StartDate, 
     st.Create_Date as EndDate 
    FROM status_change sc 
    JOIN change_tree ct ON ct.next_status_id = sc.previous_status_id AND ct.order_id = sc.order_id 
) 
SELECT * 
FROM change_tree 
WHERE status_path = '1,2,3'; 

我獲得最大的遞歸誤差。

這是一種數據的,我很期待獲得:

ORDER_ID StartDate  EndDate 
2   '2012-01-02'  '2012-01-04' 
2   '2012-01-05'  '2012-01-10' 

此工作將作爲一個報告。所以我在考慮將結果存儲在另一個表中,並且在晚上只做那些新的訂單或者哪些狀態序列已經結束。

所以在我的報告表,我必須有這兩個紀錄,並添加下一個記錄後status_change表所示:

ORDER_ID Previous_STATUS_ID Next_STATUS_ID Create_Date 
2   2     3    '2012-02-25' 

我的過程(函數應該添加到報告表中只有最後一個序列)。 希望你能明白我的意思:)

回答

2

你被逮住在一個循環中,因爲第一你選擇該行:

2   1     2    '2012-01-22' 

然後

2   2     3    '2012-01-10' 

然後

2   3     1    '2012-01-05'  

然後第一行一次又一次。您需要檢查您的數據是否足夠滿足您的報告。

或者,也許你需要以下條件添加到您的CTE:

ct.previous_status_id > sc.previous_status_id 

或者,您也可以通過被controling遞歸的這樣的水平addind參數更改腳本:

with change_tree as 
( 
    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     cast(sc.next_status_id as varchar(max)) as status_path, 
     sc.Create_Date as StartDate, 
     sc.Create_Date as EndDate, 
     1 AS deep 
    FROM status_change sc 
    WHERE previous_status_id = 1 
    AND order_id = 2 

    UNION ALL 

    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     ct.status_path + ',' + cast(sc.next_status_id as varchar(max)) 
     sc.Create_Date as StartDate, 
     st.Create_Date as EndDate, 
     ct.deep + 1 AS deep 
    FROM status_change sc 
    JOIN change_tree ct ON ct.next_status_id = sc.previous_status_id AND ct.order_id = sc.order_id 
    WHERE deep < 3 
) 
SELECT * 
FROM change_tree 
WHERE status_path = '1,2,3'; 

或者,以這種方式更改您的腳本(這將限制您的遞歸以錯誤的方式進行):

with change_tree as 
( 
    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     cast(sc.next_status_id as varchar(max)) as status_path, 
     sc.Create_Date as StartDate, 
     sc.Create_Date as EndDate 
    FROM status_change sc 
    WHERE previous_status_id = 1 
    AND order_id = 2 

    UNION ALL 

    SELECT sc.order_id, 
     sc.previous_status_id, 
     sc.next_status_id, 
     ct.status_path + ',' + cast(sc.next_status_id as varchar(max)) 
     sc.Create_Date as StartDate, 
     st.Create_Date as EndDate 
    FROM status_change sc 
    JOIN change_tree ct ON ct.next_status_id = sc.previous_status_id AND ct.order_id = sc.order_id 
    WHERE 
    '1,2,3' LIKE ct.status_path + ',' + cast(sc.next_status_id as varchar(max)) + '%' 
) 
SELECT * 
FROM change_tree 
WHERE status_path = '1,2,3'; 
+0

這是我的確切情況。我會檢查你的答案。還有一件事 - 如何逐步完成報告?爲了讓我的程序不必每天晚上都通過整個status_change表格? - @Andrey Gurinov – Misiu 2012-03-21 08:19:09

+0

我相信這可能是另一個問題的主題。但是,你爲什麼擔心你的桌子被完全重新處理?這麼大嗎?處理需要很多時間嗎? – 2012-03-21 08:23:59

+0

我有大約800k +行和大約30種模式來搜索(不同的status_path組合)。所以我認爲對每一行進行每種組合都會給我2400萬次操作。但訂單仍然被添加到表格中,我的模式也在增加。按需輸入報告,用戶點擊按鈕,稍後他應該得到該報告。這就是爲什麼我認爲聚合表是必要的。如果我錯了,請糾正我:) @Andrey Gurinov – Misiu 2012-03-21 08:33:37