2012-03-20 47 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