Issue writing Recursive query across 3 columns in same table (OrderID, OriginalOrderID, ParentOrderID)

28 Views Asked by At

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


0

There are 0 best solutions below