Sql server T-SQL,选择X、X和X发生的每行的最低日期
我遇到了一个有趣的问题,我在SQL中创建了一个视图来聚合订单上的一些数据,这样,如果某个项目缺货或我们无法填充它,我们就可以了解原因,并了解下次何时可以获得该部分的装运以及数量。这会让我们知道下一次什么时候可以订购。不幸的是,我收到的订单中多次列出了未来所有零件的购买日期,因此数据大致如下所示:Sql server T-SQL,选择X、X和X发生的每行的最低日期,sql-server,tsql,sql-function,Sql Server,Tsql,Sql Function,我遇到了一个有趣的问题,我在SQL中创建了一个视图来聚合订单上的一些数据,这样,如果某个项目缺货或我们无法填充它,我们就可以了解原因,并了解下次何时可以获得该部分的装运以及数量。这会让我们知道下一次什么时候可以订购。不幸的是,我收到的订单中多次列出了未来所有零件的购买日期,因此数据大致如下所示: Order# Part OrderQty AvailableQty PartPurchaseDate PurchaseQty 111 B 25 0
Order# Part OrderQty AvailableQty PartPurchaseDate PurchaseQty
111 B 25 0 1/1/2016 15
111 B 25 0 2/1/2016 50
112 C 500 0 1/3/2016 400
113 B 11 0 1/1/2016 15
113 B 11 0 2/1/2016 50
好的,首先我要向你道歉,否则我会用令人困惑的格式。这个项目的一部分是找出如何格式化我的问题,从而得到正确的答案。澄清上述数据是我目前得到的,只是列出了所有可能的情况,没有涉及真正的逻辑。忽略这个例子,它似乎使它更加混乱。让我们假设3张表,因为我认为这会更容易。您已获得以下详细信息:
Order# Part OrderQty
111 B 25
112 C 500
113 B 11
PartQuantity(这实际上是大量数量数据的总和,以获得我们认为“可用的”)它们都为0的原因是为了简单。在这种情况下,目前仓库中没有X零件可供我们使用,并且在特定日期之前我们不会有任何零件。在这一点上,如果我们有可用的数量,其他较小的订单可能会首先完成,因此,对于这一点,我们只是想看看PO数量估计在哪里可以完成整个订单。这并不完美,我们通常会按照收到订单的顺序来完成订单,但这只是一个粗略的预计到达时间,所以这样的假设是可以接受的。如果我们只有可用的部分填充,我们可能会保留零件或发送部分订单,以便数量不可用或订单数量已更新:
Part AvailableQTY
B 0
C 0
然后购买订单:
Part PartPurchaseDate PurchaseQty
B 1/1/2016 15
C 1/3/2016 400
B 2/1/2016 50
PartPurchaseDate是我期望收到这些零件的日期,因此我们的可用日期将在2016年1月1日从B部分的0到15。现在,由于这没有完全满足订单111的要求,因此不会收到预计到达时间,但113可以满足,预计到达时间为2016年1月1日。下面是我希望在将OrdDetail加入PartQuantity后收到的大致输出,然后从PO表中获取可以填写整个订单的最近日期。订单#112没有出现,这很好,我们只是没有该订单的预计到达时间(此时销售代表打电话给采购部投诉,这不再是我的问题)
我知道这并不是一个人想要获取的所有数据的全部,你们可能会有疑问,为什么要这样做。这不是我要复制/粘贴的东西。我只是想弄清楚一些东西是怎么工作的,所以我给你们10000英尺的信息来回答10000英尺的问题。我为延迟返回表示歉意,假期是我的借口。这是我得到的似乎有效的信息,找到每个订单的最小零件购买日期,将该值与其所属的订单一起放入一个#表中,然后将其加入到Main表中,以仅获取您需要的信息
CREATE TABLE #tmp (ordernum varchar(5), part varchar(2), orderqty int, availableqty int, partpurchasedate date, purchaseqty int)
INSERT INTO #tmp SELECT '113', 'B', 11, 0, '2016/2/1', 50 -- edited this line to add the other values
--- This is the part the partains to your question
SELECT OrderNum, MIN(partpurchasedate) minppd -- find min partpurchasedate for each order
into #tmp2 -- put it into a #table
from #tmp
where purchaseqty > orderqty -- make sure the purchase qty is > or orderqty
group by ordernum
SELECT a.*
FROM #tmp a
JOIN #tmp2 b on a.ordernum = b.ordernum -- join the tables together on their order number
where a.partpurchasedate = minppd -- only show orders whose date match the ppd we found earlier
结果就是您指定的您想要的结果。我希望这会有所帮助。此代码段似乎满足您的要求。它使用ROW_NUMBER()根据每个订单的服务日期为其创建排名,该订单的PurchaseQty大于Order Qty,然后显示与该排名关联的最早行
SELECT
c.[ORDER]
, c.Part
, c.OrderQty
, c.AvailableQty
, c.PartPurchaseDate
, c.PurchaseQty
FROM
(
SELECT
b.[ORDER]
, b.Part
, b.OrderQty
, b.AvailableQty
, b.PartPurchaseDate
, b.PurchaseQty
, Order_Rank = ROW_NUMBER()OVER(PARTITION BY b.[ORDER] ORDER BY b.PartPurchaseDate)
FROM
#ORDER b
WHERE
b.PurchaseQty > b.OrderQTY -- Only concerned when Purchase quantity greater than order quantity
) c
WHERE
c.Order_Rank = 1 -- Displays the earliest ranking
ORDER Part OrderQty AvailableQty PartPurchaseDate PurchaseQty
111 B 25 0 2016-02-01 50
113 B 11 0 2016-01-01 15
我会用解析函数来解决这个问题
select
orders.OrderId
, orders.Part
, orders.OrderQty
, orders.AvailableQty
, case
when orders.PurchaseQty > orders.OrderQty then
min(orders.PartPurchaseDate) over (partition by orders.OrderId)
else orders.PartPurchaseDate
end as PartPurchaseDate
, orders.PurchaseQty
from #Orders orders
结果
OrderId Part OrderQty AvailableQty PartPurchaseDate PurchaseQty
111 B 25 0 2016-01-01 15
111 B 25 0 2016-01-01 50
112 C 500 0 2016-01-03 400
113 B 11 0 2016-01-01 15
113 B 11 0 2016-01-01 50
背景代码
create table #Orders
(
OrderId int
, Part varchar(1)
, OrderQty int
, AvailableQty int
, PartPurchaseDate date
, PurchaseQty int
)
insert into #Orders (
OrderId
, Part
, OrderQty
, AvailableQty
, PartPurchaseDate
, PurchaseQty
)
values
(111,'B' , 25, 0 , '1/1/2016',15 )
, (111,'B' , 25, 0 , '2/1/2016',50 )
, (112,'C' , 500 , 0 , '1/3/2016',400)
, (113,'B' , 11, 0 , '1/1/2016',15 )
, (113,'B' , 11, 0 , '2/1/2016',50 )
select
orders.OrderId
, orders.Part
, orders.OrderQty
, orders.AvailableQty
, orders.min(orders.PartPurchaseDate) over (partition by orders.OrderId) as PartPurchaseDate
, orders.PurchaseQty
from #Orders orders
另外,为什么客户订单表上有履行数据?我将假设实际的表是什么
这种观点不是一个好的起点 这只会按顺序填满订单,但从视觉上看,你可以把东西扔来扔去
with cte CumOrder as
( select O1.Part, O1.order#, O1.OrderQty, Sum(O2.OrderQty) as Cum
from Order O1
join Order O2
on O2.Part = O1.Part
and O2.Order# >= O2.Order#
group by O1.Part, O1.order#, O1.OrderQty
)
, CumSuplier as
( select S1.Part, S1.Odate, S1.OrderQty, Sum(S2.OrderQty) as Cum
from Supplier S1
join Supplier S2
on S2.Part = S1.Part
and S2.Odate >= S1.Odate
group by S1.Part, S1.Odate, S1.OrderQty
)
select * from
( select CumOrder.Part, CumOrder.order#, CumOrder.OrderQty as [CumOrder.OrderQty], CumOrder.Cum as [CumOrder.Cum]
, CumSuplier.Odate as [CumSuplier.Odate]
, CumSuplier.Cum as [CumSuplier.Cum]
, (CumSuplier.Cum - CumOrder.Cum) as Net
, rowNumber over (partition by CumOrder.Part, CumOrder.order# order by CumOrder.Odate) as rn
from CumOrder
join CumSuplier
on CumSuplier.Part = CumOrder.Part
and CumSuplier.Cum >= CumOrder.Cum
) ttt
where rn = 1
order by O1.Part, O1.order#
我不明白-您在您的表格中看到113号订单中有20个可用?所有内容的可用数量均为0。您的视图显然没有足够的信息(没有大量工作)来获取订单111的任何日期。采购数量小于订单数量,所以根据行,它根本不可用。我建议你修改这个问题,或者询问另一个订单和未来的产品订单,以解决你的问题。尝试将表加入到表中,这样你就可以得到一个连续的总数。如果只给我们基本表,而不是你破坏的视图,这会容易得多。我不认为这笔交易涉及和的累积或信用订单使用量少于采购数量我不认为这是一种巧妙的方法!这或多或少是我开始尝试做的。我知道这可能不是我解决这个问题的最佳方式,但这绝对是我想要的。谢谢你的邀请input@BWoods没问题,我可以问一下原因吗?我开始使用的视图无法提供我所需要的灵活性,因此我再次将其分解(如上面的编辑)。该项目是根据ETA数据衍生的其他项目的跳板,由于我仍在学习这项技术,我仍在学习我应该问/寻找的东西。我喜欢这种先“保存”然后再进行操作的方法。但我想我希望的是一个函数,它接受多个选项作为输入,然后考虑日期/数量来计算出预计到达时间。但也许我只是想把所有想要的都集中在一个地方,让自己难堪
with cte CumOrder as
( select O1.Part, O1.order#, O1.OrderQty, Sum(O2.OrderQty) as Cum
from Order O1
join Order O2
on O2.Part = O1.Part
and O2.Order# >= O2.Order#
group by O1.Part, O1.order#, O1.OrderQty
)
, CumSuplier as
( select S1.Part, S1.Odate, S1.OrderQty, Sum(S2.OrderQty) as Cum
from Supplier S1
join Supplier S2
on S2.Part = S1.Part
and S2.Odate >= S1.Odate
group by S1.Part, S1.Odate, S1.OrderQty
)
select * from
( select CumOrder.Part, CumOrder.order#, CumOrder.OrderQty as [CumOrder.OrderQty], CumOrder.Cum as [CumOrder.Cum]
, CumSuplier.Odate as [CumSuplier.Odate]
, CumSuplier.Cum as [CumSuplier.Cum]
, (CumSuplier.Cum - CumOrder.Cum) as Net
, rowNumber over (partition by CumOrder.Part, CumOrder.order# order by CumOrder.Odate) as rn
from CumOrder
join CumSuplier
on CumSuplier.Part = CumOrder.Part
and CumSuplier.Cum >= CumOrder.Cum
) ttt
where rn = 1
order by O1.Part, O1.order#