根据SQL Server中提供的条件分配产品名称

时间:2018-08-30 01:14:06

标签: sql sql-server sql-server-2012 sql-server-2008-r2

我正在尝试根据以下条件编写sql查询:

产品

Product Table

订购

enter image description here

产品表有3列,基于以下查询: 创建产品(MasterProduct nvarchar(50),Productkey int,ProductName nvarchar(50))

“订单表”基于以下查询具有3列: 创建订单(MasterProduct nvarchar(50),Orderno int,Productkey int,ParentProduct int)

场景:

应基于以下条件,将“产品”表中的“ MasterProduct”列分配给“订单”表中的特定订单

1)如果特定主产品的产品表中的所有产品密钥与订单表中的订单号匹配

AND

第一个ProductKey是其在订购表中直接产品密钥的父代

示例:由于“产品表”中的产品键1和2都存在于S1中,并且产品键1是父产品,因此将订单号“ S1”分配给Kebab作为订单表的主产品产品密钥2和4的密钥。

另一方面,没有为订单号'S2'分配任何主产品(NULL),因为它只具有'1'作为产品密钥,而'2'不存在,否则将被分配Kebab。

>

S3也被分配了一个Subway,因为它具有该订单号的产品表中存在的产品密钥30和31,并且作为父产品的产品密钥30被分配给至少一个子产品'31'。 / p>

尽管S4具有Subway(30,31)的所有产品密钥,但未分配任何主产品,因为未将作为父产品的30分配给任何子产品。

1 个答案:

答案 0 :(得分:0)

这有点令人费解,但这是一个有效的版本:

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个可能使事情复杂化的候选对象。

然后在主查询中,有一个内部子查询,该子查询将所有父级和子级行与产品模型进行比较,并检查我们是否具有所有产品。它必须为每个候选父母执行此操作,然后再次将其汇总到整个订单中。如果有两个候选父母(其中一个满意并且一个没有),则必须这样做。

最后,如果我们拥有所有产品,则将其加入订单以返回主产品;否则,则返回null。