Sql server 2005 TSQL递归-表中具有双重值的最大递归错误
相关问题: 我要问第二个关于递归的问题,因为这一次它是不同的(在我看来),所以请不要删除它 我有一个包含值的表:Sql server 2005 TSQL递归-表中具有双重值的最大递归错误,sql-server-2005,tsql,recursive-query,Sql Server 2005,Tsql,Recursive Query,相关问题: 我要问第二个关于递归的问题,因为这一次它是不同的(在我看来),所以请不要删除它 我有一个包含值的表: ORDER_ID Previous_STATUS_ID Next_STATUS_ID Create_Date 2 null 1 '2012-01-02' 2 1 2 '2012-01-03' 2
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 1 2 '2012-01-22'
然后
然后
然后一次又一次地排第一行。您需要检查您的数据是否与您的报告足够一致
或者,您可能需要在CTE中添加以下条件:
ct.previous_status_id > sc.previous_status_id
或者,您可以通过控制递归级别的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';
这正是我现在的处境。我来核对你的答案。还有一件事-如何以增量方式完成该报告?这样我的程序就不必每天晚上检查整个状态变更表了@安德烈·古里诺维奇认为,这可能是另一个问题的主题。但你为什么担心你的桌子会被完全重新加工呢?有这么大吗?处理需要很多时间吗?我有大约800k+行和大约30个模式要搜索(不同的状态和路径组合)。所以我认为,对每一行进行每一次组合都会给我带来大约2400万次操作。但订单仍然被添加到表中,我的模式数量也在增加。报告类型为“按需”,所以用户点击按钮,片刻后他应该会得到该报告。这就是为什么我认为聚合表是必要的。如果我错了,请纠正我:)@Andrey GurinovCan您的旧数据已更改?我的意思是,增量过程应该只向聚合表添加新记录,还是应该更新/删除旧记录?对于30种模式,我认为我建议的最后一个选项将是最有用的。您可以在CTE和外部选择中使用OR运算符组合不同的状态路径组合。
ct.previous_status_id > sc.previous_status_id
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';