根据 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 中给定的条件分配产品名称的主要内容,如果未能解决你的问题,请参考以下文章