根据 SQL Server 中给定的条件分配产品名称

Posted

技术标签:

【中文标题】根据 SQL Server 中给定的条件分配产品名称【英文标题】:Assign a product name based on the conditions given in SQL Server 【发布时间】:2018-08-30 01:14:05 【问题描述】:

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

产品

订购

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

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

场景:

产品表中的“MasterProduct”列应根据以下条件分配给订单表中的特定订单

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

第一个 ProductKey 是 Order Table 中其直接产品密钥的父代

示例:订单号“S1”被分配一个烤肉串作为订单表的主产品,因为产品表中的产品密钥 1 和 2 都存在于 S1 中,并且产品密钥 1 是父产品产品密钥 2 和 4 的密钥。

另一方面,订单号“S2”没有分配任何主产品 (NULL),因为它只有“1”作为产品密钥,并且“2”不存在,否则它将被分配一个烤肉串。

S3 也被分配了一个 Subway,因为它具有来自该订单号的产品表中的产品密钥 30 和 31,并且作为父产品的产品密钥 30 被分配给它“31”的至少一个子产品。

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

【问题讨论】:

如果订单中的产品匹配不同的主产品怎么办?什么定义了订单以知道哪个是订单中的第一个产品密钥?请不要使用图片发布示例数据。理想情况下使用INSERT 语句或至少一些文本表。 主产品订单中的产品会有所不同。所以订单中的product key按OrderLineNumberKey列排序(表中没有包含)。 那么请在您的问题中添加OrderLineNumberKey。为什么'S1' 中的7'S3' 中的35 不违反第二个条件? OrderLineNumber 已添加。 S1 具有产品密钥 7 ,但作为产品密钥 2 的子产品被分配给产品密钥 1(S1 的父产品),因此另一个不重要。主要的是订单的第二个产品密钥应该始终有一个父产品,以便为其分配一个“主产品”,而订单表中的 S1 产品密钥 7 是第四个产品。 S3 也有类似的含义。我希望你明白我的意思。 【参考方案1】:

这有点令人费解,但这是一个工作版本:

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 个可能的候选者,这使事情变得复杂。

然后在主查询中,有一个内部子查询将所有父子行与产品模型进行比较,并检查我们是否拥有所有产品。它必须为每个候选父母执行此操作,然后将其第二次汇总以获取整个订单。如果有两个候选父母,一个满意,一个不满意,它必须这样做。

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

【讨论】:

嗨,汤姆,感谢您的询问。我运行了查询,但主产品的所有内容都分配了 NULL。这可能是什么原因? 你是用我的样本数据还是你的实际数据运行的?我只是将解决方案剪切并粘贴到查询窗口中,它运行良好。

以上是关于根据 SQL Server 中给定的条件分配产品名称的主要内容,如果未能解决你的问题,请参考以下文章

需要一个 SQL 查询来从 SQL Server 数据库中获取特定条件下给定时间段的数据

Sql Server 2008中根据条件求和

如何根据多个条件从 SQL Server 中删除大量数据

在 SQL Server 中根据条件创建视图

如何在sql server中根据条件生成序列号

根据 SQL Server 中的条件计数