递归 CTE 查询循环直到满足条件
Recursive CTE query looping until conditions are met
我正在尝试编写一个查询,它将递归地寻找初始位置或部件号已更改。
有一个 table stktrans
保存任何订单的 IN 和 OUT 交易.
当发送某些东西时 OUT 它会有一个 IN_Nr 可以用来追溯 IN 事务。 OrderNr 将 IN 链接到 OUT
编辑:给定任何 IN_Nr 我希望能够追溯到购买它的原始订单。在下面的 table 中 - TransID 1。但显示事件的完整时间线,例如下面的 table。
传输ID
部分
IN_Nr
OUT_Nr
订单号
类型
8
123-1
232753
232233
888777
输出
7
123-1
232753
空
125707
输入
6
123-1
203944
224789
125707
输出
5
123-1
203944
空
123332
输入
4
123-1
179409
198306
123332
输出
3
123-1
179409
空
111222
输入
2
123-1
176573
171516
111222
输出
1
123-1
176573
空
666000
输入
回溯之间的规律如下图:
目前,我有一个非常非动态的查询,它可以从任何给定的 IN_Nr:
追溯 4 个级别
DECLARE @IN_Nr INT = 232753
;WITH StkOUT_CTE AS (
SELECT
ST.TransID,
ST.Part,
ST.IN_Nr,
ST.OUT_Nr,
ST.OrderNr,
ST.Type
FROM
StkTrans ST
WHERE
OUT_Nr IS NOT NULL
AND ST.Type = 'OUT'
),
StkIN_CTE AS (
SELECT
ST.TransID,
ST.Part,
ST.IN_Nr,
ST.OUT_Nr,
ST.OrderNr,
ST.Type
FROM
StkTrans ST
INNER JOIN StkOUT_CTE SI ON SI.IN_Nr = ST.IN_Nr
WHERE
ST.Type = 'IN'
)
SELECT
*
FROM
(
SELECT
1 RowOrder, *
FROM
StkOUT_CTE
WHERE IN_Nr = @IN_Nr
UNION
SELECT
2 RowOrder, *
FROM
StkIN_CTE
WHERE IN_Nr = @IN_Nr
UNION
SELECT 3 RowOrder, *
FROM
StkOUT_CTE
WHERE
OrderNr = (SELECT OrderNr FROM StkIN_CTE WHERE IN_Nr = @IN_Nr)
UNION
SELECT 4 RowOrder, *
FROM
StkIN_CTE
WHERE
IN_Nr = (
SELECT IN_Nr
FROM
StkOUT_CTE
WHERE
OrderNr = (SELECT OrderNr FROM StkIN_CTE WHERE IN_Nr = @IN_Nr))
) ST
要创建类似的设置:
CREATE TABLE StkTrans (
TransID INT,
Part VARCHAR(25),
IN_Nr INT,
OUT_Nr INT,
OrderNr INT,
Type VARCHAR(3)
)
INSERT INTO StkTrans
(TransID, Part, IN_Nr, OUT_Nr, OrderNr, Type)
VALUES
(1, '123-1', 176573, NULL, 666000, 'IN' ),
(2, '123-1', 176573, 171516, 111222, 'OUT' ),
(3, '123-1', 179409, NULL, 111222, 'IN' ),
(4, '123-1', 179409, 198306, 123332, 'OUT' ),
(5, '123-1', 203944, NULL, 123332, 'IN' ),
(6, '123-1', 203944, 224789, 125707, 'OUT' ),
(7, '123-1', 232753, NULL, 125707, 'IN' ),
(8, '123-1', 232753, 232233, 888777, 'OUT' )
任何可能为我指明如何递归使用 CTE 的正确方向的指导都很棒!
字里行间,也许这就是您想要的?
WITH rCTE AS(
SELECT *,
1 AS Iteration
FROM dbo.StkTrans ST
WHERE ST.IN_Nr = '232753'
AND ST.[Type] = 'IN'
UNION ALL
SELECT STi.*,
r.Iteration + 1
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
JOIN rCTE r ON STo.OrderNr = r.OrderNr
WHERE STo.[Type] = 'Out'
AND STi.[Type] = 'In')
SELECT TOP (1) TransID
FROM rCTE
ORDER BY ROW_NUMBER() OVER (ORDER BY Iteration DESC);
编辑:
也许这就是您所追求的。我现在也对 rCTE 中的第一个数据集进行参数化,以便于针对其他值进行测试。
DECLARE @IN_Nr int = 232753;
WITH rCTE AS(
SELECT V.*,
1 AS Iteration
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
CROSS APPLY (VALUES(STo.TransID,STo.Part,STo.IN_Nr,STo.OUT_Nr,STo.OrderNr,STo.[Type]),
(STi.TransID,STi.Part,STi.IN_Nr,STi.OUT_Nr,STi.OrderNr,STi.[Type]))V(TransID,Part,IN_Nr,OUT_Nr,OrderNr,[Type])
WHERE STo.IN_Nr = @IN_Nr
AND STo.[Type] = 'OUT'
AND STi.[Type] = 'In'
UNION ALL
SELECT V.*,
r.Iteration + 1
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
JOIN rCTE r ON STo.OrderNr = r.OrderNr
AND r.[Type] = 'In'
CROSS APPLY (VALUES(STo.TransID,STo.Part,STo.IN_Nr,STo.OUT_Nr,STo.OrderNr,STo.[Type]),
(STi.TransID,STi.Part,STi.IN_Nr,STi.OUT_Nr,STi.OrderNr,STi.[Type]))V(TransID,Part,IN_Nr,OUT_Nr,OrderNr,[Type])
WHERE STo.[Type] = 'Out'
AND STi.[Type] = 'In')
SELECT TransID,
Part,
IN_Nr,
OUT_Nr,
OrderNr,
[Type]
FROM rCTE
ORDER BY TransID DESC;
我正在尝试编写一个查询,它将递归地寻找初始位置或部件号已更改。
有一个 table stktrans
保存任何订单的 IN 和 OUT 交易.
当发送某些东西时 OUT 它会有一个 IN_Nr 可以用来追溯 IN 事务。 OrderNr 将 IN 链接到 OUT
编辑:给定任何 IN_Nr 我希望能够追溯到购买它的原始订单。在下面的 table 中 - TransID 1。但显示事件的完整时间线,例如下面的 table。
传输ID | 部分 | IN_Nr | OUT_Nr | 订单号 | 类型 |
---|---|---|---|---|---|
8 | 123-1 | 232753 | 232233 | 888777 | 输出 |
7 | 123-1 | 232753 | 空 | 125707 | 输入 |
6 | 123-1 | 203944 | 224789 | 125707 | 输出 |
5 | 123-1 | 203944 | 空 | 123332 | 输入 |
4 | 123-1 | 179409 | 198306 | 123332 | 输出 |
3 | 123-1 | 179409 | 空 | 111222 | 输入 |
2 | 123-1 | 176573 | 171516 | 111222 | 输出 |
1 | 123-1 | 176573 | 空 | 666000 | 输入 |
回溯之间的规律如下图:
目前,我有一个非常非动态的查询,它可以从任何给定的 IN_Nr:
追溯 4 个级别
DECLARE @IN_Nr INT = 232753
;WITH StkOUT_CTE AS (
SELECT
ST.TransID,
ST.Part,
ST.IN_Nr,
ST.OUT_Nr,
ST.OrderNr,
ST.Type
FROM
StkTrans ST
WHERE
OUT_Nr IS NOT NULL
AND ST.Type = 'OUT'
),
StkIN_CTE AS (
SELECT
ST.TransID,
ST.Part,
ST.IN_Nr,
ST.OUT_Nr,
ST.OrderNr,
ST.Type
FROM
StkTrans ST
INNER JOIN StkOUT_CTE SI ON SI.IN_Nr = ST.IN_Nr
WHERE
ST.Type = 'IN'
)
SELECT
*
FROM
(
SELECT
1 RowOrder, *
FROM
StkOUT_CTE
WHERE IN_Nr = @IN_Nr
UNION
SELECT
2 RowOrder, *
FROM
StkIN_CTE
WHERE IN_Nr = @IN_Nr
UNION
SELECT 3 RowOrder, *
FROM
StkOUT_CTE
WHERE
OrderNr = (SELECT OrderNr FROM StkIN_CTE WHERE IN_Nr = @IN_Nr)
UNION
SELECT 4 RowOrder, *
FROM
StkIN_CTE
WHERE
IN_Nr = (
SELECT IN_Nr
FROM
StkOUT_CTE
WHERE
OrderNr = (SELECT OrderNr FROM StkIN_CTE WHERE IN_Nr = @IN_Nr))
) ST
要创建类似的设置:
CREATE TABLE StkTrans (
TransID INT,
Part VARCHAR(25),
IN_Nr INT,
OUT_Nr INT,
OrderNr INT,
Type VARCHAR(3)
)
INSERT INTO StkTrans
(TransID, Part, IN_Nr, OUT_Nr, OrderNr, Type)
VALUES
(1, '123-1', 176573, NULL, 666000, 'IN' ),
(2, '123-1', 176573, 171516, 111222, 'OUT' ),
(3, '123-1', 179409, NULL, 111222, 'IN' ),
(4, '123-1', 179409, 198306, 123332, 'OUT' ),
(5, '123-1', 203944, NULL, 123332, 'IN' ),
(6, '123-1', 203944, 224789, 125707, 'OUT' ),
(7, '123-1', 232753, NULL, 125707, 'IN' ),
(8, '123-1', 232753, 232233, 888777, 'OUT' )
任何可能为我指明如何递归使用 CTE 的正确方向的指导都很棒!
字里行间,也许这就是您想要的?
WITH rCTE AS(
SELECT *,
1 AS Iteration
FROM dbo.StkTrans ST
WHERE ST.IN_Nr = '232753'
AND ST.[Type] = 'IN'
UNION ALL
SELECT STi.*,
r.Iteration + 1
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
JOIN rCTE r ON STo.OrderNr = r.OrderNr
WHERE STo.[Type] = 'Out'
AND STi.[Type] = 'In')
SELECT TOP (1) TransID
FROM rCTE
ORDER BY ROW_NUMBER() OVER (ORDER BY Iteration DESC);
编辑: 也许这就是您所追求的。我现在也对 rCTE 中的第一个数据集进行参数化,以便于针对其他值进行测试。
DECLARE @IN_Nr int = 232753;
WITH rCTE AS(
SELECT V.*,
1 AS Iteration
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
CROSS APPLY (VALUES(STo.TransID,STo.Part,STo.IN_Nr,STo.OUT_Nr,STo.OrderNr,STo.[Type]),
(STi.TransID,STi.Part,STi.IN_Nr,STi.OUT_Nr,STi.OrderNr,STi.[Type]))V(TransID,Part,IN_Nr,OUT_Nr,OrderNr,[Type])
WHERE STo.IN_Nr = @IN_Nr
AND STo.[Type] = 'OUT'
AND STi.[Type] = 'In'
UNION ALL
SELECT V.*,
r.Iteration + 1
FROM dbo.StkTrans STo
JOIN dbo.StkTrans STi ON STo.IN_Nr = STi.IN_Nr
JOIN rCTE r ON STo.OrderNr = r.OrderNr
AND r.[Type] = 'In'
CROSS APPLY (VALUES(STo.TransID,STo.Part,STo.IN_Nr,STo.OUT_Nr,STo.OrderNr,STo.[Type]),
(STi.TransID,STi.Part,STi.IN_Nr,STi.OUT_Nr,STi.OrderNr,STi.[Type]))V(TransID,Part,IN_Nr,OUT_Nr,OrderNr,[Type])
WHERE STo.[Type] = 'Out'
AND STi.[Type] = 'In')
SELECT TransID,
Part,
IN_Nr,
OUT_Nr,
OrderNr,
[Type]
FROM rCTE
ORDER BY TransID DESC;