I have a SQL table with, in particular, 3 columns of interest: OrderID, OriginalOrderID, ParentOrderID
For reference, OrderID is the start of an order, while the other two cols are to denote "spawned" orders (refunds, chargebacks, etc. against the initial order). OrderID is the PK, while the other 2 columns each have their own index.
I have written the following recursive query. The intent being to search for a Order-ID and return all rows where that Order-ID value is found in any of the 3 aforementioned columns (iow, all related Order-IDs).
Obviously, I want the script to be efficient, reading only the associated rows versus everything in the table (inner joins and indexes should be sufficient to avoid that).
For the purposes of this post, here's some example data:
declare @MyTable table (OrderID int, OriginalOrderID int, ParentOrderID int)
insert into @MyTable values
(437, 421, 436)
,(436, 420, null)
,(421, null, 420)
,(420, null, null)
Desired Results:
For example, when @SearchOrderID = 421, the resulting @OrderIDs (variable-based table) should have: 420 1 (isParent) 421 0 436 0 437 0
In other words, running the query with @SearchOrderID set to 420 or 421 or 436 or 437 would result in finding all four of the related Order-IDs.
I realize my example dataset is only these 4 IDs .. but I hoped it would be sufficient to describe the goal.
That being said, here's my attempt at the CTE. It seems to be working well .. but I question the approach. Is there a more efficient way? Thanks, in advance, for the insight and explanation.
DECLARE @OrderIDs table (OrderId int, isParent bit)
-- ----------------------------\
-- Define the Order Id .. can be the onset Order ID or Spawn/Child/Conversion ID:
DECLARE @SearchOrderID as int = '437'
-- ----------------------------/
-- Build CTE to find all related (parent / child) OrderIDs:
;WITH
Children as (
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
where xo.orderId = @SearchOrderID
UNION ALL -- Add all rows from 1st query results to the subsequent recursive query's results
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Children co on co.OrderID = xo.OriginalOrderID
UNION ALL
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Children co on co.OrderID = xo.ParentOrderID
),
Parent as (
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
where xo.orderId = @SearchOrderID
UNION ALL
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Parent po on po.OriginalOrderID = xo.OrderID
UNION ALL
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Parent po on po.ParentOrderID = xo.OrderID
),
MixMatch as (
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Children co on co.OriginalOrderID = xo.OrderID
UNION
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Children co on co.ParentOrderID = xo.OrderID
UNION
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Parent co on co.OriginalOrderID = xo.OrderID
UNION
select xo.orderId
, xo.originalOrderId
, xo.parentOrderId
from @MyTable xo
inner join Parent co on co.ParentOrderID = xo.OrderID
)
insert into @OrderIDs
select orderId, case when (OriginalOrderID is null) and (ParentOrderID is null) then 1 else 0 end from Children
union
select orderId, case when (OriginalOrderID is null) and (ParentOrderID is null) then 1 else 0 end from Parent
union
select orderId, case when (OriginalOrderID is null) and (ParentOrderID is null) then 1 else 0 end from MixMatch
-- Show Parent / Child relationship:
select * from @OrderIDs
order by IsParent desc, OrderId