Это немного запутанно, но вот рабочая версия:
declare @p table(MasterProduct nvarchar(50), Productkey int, ProductName nvarchar(50))
declare @o table(OrderLineNumberKey int, Orderno int, Productkey int, ParentProduct int)
insert @p values('kebab',1,'chicken'),('kebab',2,'mayo'),('subway',30,'bread'),('subway',31,'salad')
insert @o values(1,1,1,null),(2,1,2,1),(3,1,4,1),(4,1,7,null)
insert @o values(1,2,1,null),(2,2,9,null),(3,2,14,1)
insert @o values(1,3,30,null),(2,3,31,30),(3,3,35,null)
insert @o values(1,4,30,null),(2,4,31,null),(3,4,39,null)
;with ParentChild as (
select o.orderno, o.ProductKey as TopProductKey, o.productkey, p.masterproduct
from @o o
join @p p on p.productKey=o.ProductKey
where parentproduct is null
union all
select pc.orderno,pc.ProductKey as TopProductKey,o.productkey,p.masterproduct
from @o o
join @p p on p.productKey=o.ProductKey
join ParentChild pc on pc.orderno=o.orderno and pc.ProductKey=o.ParentProduct
)
select case when HaveAll=1 then ordercheck.masterproduct end as masterproduct,
o.orderno, o.productkey,o.parentproduct
from @o o
left join(
select orderno, masterproduct, max(HaveAll) as HaveAll from (
select pc1.orderno, p.masterproduct, min(case when pc2.productkey is null then 0 else 1 end) as HaveAll
from ParentChild pc1
join @p p on p.masterproduct=pc1.masterproduct
left join ParentChild pc2 on pc2.orderno=pc1.orderno and pc2.MasterProduct=p.MasterProduct and pc2.productkey=p.productkey and pc2.topproductkey=pc1.topproductkey
where pc1.TopProductKey=pc1.ProductKey
group by pc1.orderno, p.masterproduct, pc1.TopProductKey
) q
group by orderno, masterproduct
) ordercheck on ordercheck.orderno=o.orderno
Чтобы объяснить это, во-первых, в CTE мы рекурсивно просматриваем приказы, ищем всех возможных родителей с нулевым родителем и находим все их дочерние строки. Вы увидите, что у заказа 4 есть 2 возможных кандидата, которые усложняют ситуацию.
Затем в основном запросе есть внутренний подзапрос, который сравнивает все родительские + дочерние строки с моделью продукта и проверяет, что у нас есть все продукты. Он должен сделать это для каждого из родителей-кандидатов, а затем свернуть это во второй раз для общего заказа. Это должно быть сделано в случае, если было два кандидата в родители, один из которых был удовлетворен, а другой - нет.
Наконец, мы присоединяем это к заказам на возврат основного продукта, если у нас были все продукты, или к нулю, если у нас его нет.