Sql 详细地说,这正是我要寻找的。我想不起来,但现在我明白了。希望将来我能自己写一个类似的查询,有这样的复杂性。非常感谢您详细解释,这正是我要搜索的。我想不起来,但现在我明白了。希望将来我能用这个复杂的问题自己写一个类似的查询谢谢你,安迪!这是一个非常复杂的查询
Sql 详细地说,这正是我要寻找的。我想不起来,但现在我明白了。希望将来我能自己写一个类似的查询,有这样的复杂性。非常感谢您详细解释,这正是我要搜索的。我想不起来,但现在我明白了。希望将来我能用这个复杂的问题自己写一个类似的查询谢谢你,安迪!这是一个非常复杂的查询,sql,sql-server,Sql,Sql Server,详细地说,这正是我要寻找的。我想不起来,但现在我明白了。希望将来我能自己写一个类似的查询,有这样的复杂性。非常感谢您详细解释,这正是我要搜索的。我想不起来,但现在我明白了。希望将来我能用这个复杂的问题自己写一个类似的查询谢谢你,安迪!这是一个非常复杂的查询,我还不太理解它,因为我一般很难理解CTE。但我会尝试你的和Clockworks版本的Anks——就我个人而言,我会选择Clockworks(+1)。我不认为您可以避免递归CTE,但鉴于您可以避免,您应该避免!非常感谢你,安迪!这是一个非常复杂
详细地说,这正是我要寻找的。我想不起来,但现在我明白了。希望将来我能自己写一个类似的查询,有这样的复杂性。非常感谢您详细解释,这正是我要搜索的。我想不起来,但现在我明白了。希望将来我能用这个复杂的问题自己写一个类似的查询谢谢你,安迪!这是一个非常复杂的查询,我还不太理解它,因为我一般很难理解CTE。但我会尝试你的和Clockworks版本的Anks——就我个人而言,我会选择Clockworks(+1)。我不认为您可以避免递归CTE,但鉴于您可以避免,您应该避免!非常感谢你,安迪!这是一个非常复杂的查询,我还不太理解它,因为我一般很难理解CTE。但我会尝试你的和Clockworks版本的Anks——就我个人而言,我会选择Clockworks(+1)。我不认为您可以避免递归CTE,但鉴于您可以避免,您应该避免! DocNum ItemCode Planned Qty WhsCode BinCode QuantityToPick 901903 A00001 12.000000 98 98-A001 7.000000 901903 A00001 12.000000 98 98-A002 5.000000 --sum of 5 and 7 makes 12 901904 A00001 17.000000 98 98-A001 7.000000 901904 A00001 17.000000 98 98-A002 6.000000 901904 A00001 17.000000 98 98-A003 4.000000 --sum of 7,6 and 4 makes 17 But I want to have this result: DocNum ItemCode Planned Qty WhsCode BinCode QuantityToPick 901903 A00001 12.000000 98 98-A001 7.000000 901903 A00001 12.000000 98 98-A002 5.000000 --sum of 5 and 7 makes 12 -- continue from bin code 98A002 for the new docnum as we had 5 out of 6 where consumed 901904 A00001 17.000000 98 98-A002 1.000000 901904 A00001 17.000000 98 98-A003 12.000000 901904 A00001 17.000000 98 98-A004 4.000000 --sum of 1,12 and 4 makes 17
-- Create Tables for Subquerys + insert relevant data
CREATE TABLE [dbo].[WOR1](-- Removed the unimportant columns
[DocEntry] [int] NOT NULL,
[LineNum] [int] NOT NULL,
[ItemCode] [nvarchar](50) NULL,
[PlannedQty] [numeric](19, 6) NULL,
[IssuedQty] [numeric](19, 6) NULL,
[wareHouse] [nvarchar](8) NULL
)
INSERT INTO [dbo].[WOR1]
VALUES(154 ,0 ,'A00001' ,12.000000 ,0.000000, '01')
,(154 ,1 ,'P10001' ,12.000000 ,0.000000, '01')
,(154 ,2 ,'L10001' ,12.000000 ,0.000000, '01')
,(155 ,0 ,'A00001' ,17.000000 ,0.000000, '01')
,(155 ,1 ,'P10001' ,17.000000 ,0.000000, '01')
,(155 ,2 ,'L10001' ,17.000000 ,0.000000, '01')
CREATE TABLE [dbo].[OWOR](-- Removed the unimportant columns
[DocEntry] [int] NOT NULL,
[DocNum] [int] NOT NULL,
[Status] [char](1) NULL
)
INSERT INTO [dbo].[OWOR]
VALUES( 154, 901903, 'R')
,( 155, 901904, 'R')
CREATE TABLE [dbo].[OIBQ](-- Removed the unimportant columns
[ItemCode] [nvarchar](50) NOT NULL,
[BinAbs] [int] NOT NULL,
[OnHandQty] [numeric](19, 6) NULL,
[WhsCode] [nvarchar](8) NULL
)
INSERT INTO [dbo].[OIBQ]
VALUES('A00001', 7, 15.000000, '98')
,('A00001', 2, 7.000000, '98')
,('A00001', 3, 6.000000, '98')
,('A00001', 4, 12.000000, '98')
CREATE TABLE [dbo].[OBIN](-- Removed the unimportant columns
[AbsEntry] [int] NOT NULL,
[BinCode] [nvarchar](228) NOT NULL,
[WhsCode] [nvarchar](8) NULL
)
INSERT INTO [dbo].[OBIN]
VALUES(1, '98-SYSTEM-BIN-LOCATION', '98')
,(2, '98-A001', '98')
,(3, '98-A002', '98')
,(4, '98-A003', '98')
,(5, '98-A004', '98')
,(6, '98-A005', '98')
,(7, '98-A006', '98')
SELECT
WOPICK.DocNum,
WOPICK.ItemCode,
WOPICK.Quantity as 'Planned Qty',
BINSTOCK.WhsCode,
BINSTOCK.BinCode,
CASE WHEN (BINSTOCK.Quantity -(BINSTOCK.RunningTotalQty - WOPICK.Quantity)) <BINSTOCK.Quantity
THEN (BINSTOCK.Quantity -(BINSTOCK.RunningTotalQty - WOPICK.Quantity))
ELSE BINSTOCK.Quantity END as 'QuantityToPick'-- FinalQty
FROM (
SELECT IBQ.ItemCode, SUM(IBQ.OnHandQty)as 'Quantity',BIN.WhsCode, BIN.BinCode ,
SUM(SUM(OnHandQty)) OVER (PARTITION BY IBQ.ItemCode
ORDER BY IBQ.ItemCode,BIN.BinCode ) as 'RunningTotalQty'
FROM OIBQ IBQ INNER JOIN OBIN BIN on IBQ.BinAbs = BIN.AbsEntry
GROUP BY IBQ.ItemCode, BIN.WhsCode, BIN.BinCode
) BINSTOCK
INNER JOIN (
SELECT distinct WOR.DocNum, WOR1.LineNum, WOR1.ItemCode, WOR1.PlannedQty - WOR1.IssuedQty as 'Quantity'
FROM OWOR WOR
INNER JOIN WOR1 WOR1 on WOR.DocEntry = WOR1.DocEntry
INNER JOIN OIBQ IBQ on IBQ.ItemCode = WOR1.ItemCode
where WOR.Status = 'R'
) WOPICK on BINSTOCK.ItemCode = WOPICK.ItemCode
WHERE BINSTOCK.RunningTotalQty - BINSTOCK.Quantity < WOPICK.Quantity
order by WOPICK.LineNum;
CREATE TABLE [dbo].[BINSTOCK](
ItemCode NVARCHAR(10) NOT NULL
,Quantity DECIMAL (19,6) NOT NULL
,WhsCode INT NOT NULL
,BinCode NVARCHAR (10) NOT NULL
,RunningTotalQty DECIMAL (19,6) NOT NULL
)
INSERT INTO [dbo].[BINSTOCK]
VALUES('A00001' , 7.000000, 98, '98-A001' , 7.000000),
('A00001' , 6.000000, 98, '98-A002' , 13.000000),
('A00001' , 12.000000, 98, '98-A003' , 25.000000),
('A00001' , 15.000000, 98, '98-A006' , 40.000000)
CREATE TABLE [dbo].[WOPICK](
DocNum INT NOT NULL
,LineNum INT NOT NULL
,ItemCode NVARCHAR (10) NOT NULL
,Quantity DECIMAL (19,6) NOT NULL
)
INSERT INTO [dbo].[WOPICK]
VALUES(901903,0,'A00001',12.000000),
(901904,0,'A00001',17.000000)
SELECT
WOPICK.DocNum,
WOPICK.ItemCode,
WOPICK.Quantity as 'Planned Qty',
BINSTOCK.WhsCode,
BINSTOCK.BinCode,
CASE WHEN (BINSTOCK.Quantity -(BINSTOCK.RunningTotalQty - WOPICK.Quantity)) <BINSTOCK.Quantity
THEN (BINSTOCK.Quantity -(BINSTOCK.RunningTotalQty - WOPICK.Quantity))
ELSE BINSTOCK.Quantity END as 'QuantityToPick'-- FinalQty
FROM BINSTOCK
INNER JOIN WOPICK on BINSTOCK.ItemCode = WOPICK.ItemCode
WHERE BINSTOCK.RunningTotalQty - BINSTOCK.Quantity < WOPICK.Quantity
order by WOPICK.LineNum;
WITH Bin AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY ItemCode ORDER BY BinCode) AS BinRank
FROM BINSTOCK
), Pick AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY ItemCode ORDER BY DocNum) AS PickRank
FROM WOPICK
), BinPick AS (
SELECT
b.ItemCode,
b.Quantity AS BinQty,
b.BinCode,
b.BinRank,
p.Quantity AS PickQty,
p.DocNum,
p.PickRank,
CAST (
CASE
WHEN b.Quantity < p.Quantity
THEN b.Quantity
ELSE p.Quantity
END
AS DECIMAL) AS Picked,
CAST (
CASE
WHEN b.Quantity < p.Quantity
THEN p.Quantity - b.Quantity
ELSE 0
END
AS DECIMAL) AS Required,
CAST (
CASE
WHEN b.Quantity < p.Quantity
THEN 0
ELSE b.Quantity - p.Quantity
END
AS DECIMAL) AS Remaining,
CAST (
CASE
WHEN b.Quantity < p.Quantity
THEN null
ELSE b.BinRank
END
AS NVARCHAR) AS LastFullBinRank
FROM Bin b
JOIN Pick p ON p.ItemCode = b.ItemCode
WHERE b.BinRank = 1
AND p.PickRank = 1
UNION ALL
SELECT
ItemCode,
BinQty,
BinCode,
BinRank,
PickQty,
DocNum,
PickRank,
CAST (
CASE WHEN Remaining < Required
THEN Remaining
ELSE Required
END
AS DECIMAL) AS Picked,
CAST (
CASE WHEN Remaining < Required
THEN Required - Remaining
ELSE 0
END
AS DECIMAL) AS Required,
CAST (
CASE WHEN Remaining < Required
THEN 0
ELSE Remaining - Required
END
AS DECIMAL) AS Remaining,
CAST (
CASE WHEN Remaining < Required
THEN null
ELSE BinRank
END
AS NVARCHAR) AS LastFullBinRank
FROM (
SELECT
b.ItemCode,
b.Quantity AS BinQty,
b.BinCode,
b.BinRank,
p.Quantity AS PickQty,
p.DocNum,
p.PickRank,
bp.DocNum AS PrevDocNum,
bp.Picked,
bp.LastFullBinRank,
CASE WHEN p.DocNum = bp.DocNum
-- Same order. Continue with required from previous.
THEN bp.Required
-- New order. Required is new order quantity.
ELSE p.Quantity
END
AS Required,
CASE WHEN p.DocNum = bp.DocNum
-- Same order. Hence fresh bin. Use quanity from this bin.
THEN b.Quantity
-- New order. Hence used bin. Use remaining carried over.
ELSE bp.Remaining
END
AS Remaining
FROM BinPick bp
JOIN Pick p
ON p.ItemCode = bp.ItemCode
AND (
-- Order complete. Move to next order
(bp.Required = 0 AND p.PickRank = bp.PickRank + 1)
OR
-- Order incomlete. Continue with current Order
(bp.Required > 0 AND p.PickRank = bp.PickRank)
)
JOIN Bin b
ON b.ItemCode = bp.ItemCode
AND (
-- Order complete. Resume at last full bin.
(bp.Required = 0 AND b.BinRank = bp.LastFullBinRank)
OR
-- Order incomlete. Move to next bin.
(bp.Required > 0 AND bp.LastFullBinRank IS NULL AND b.BinRank = bp.BinRank + 1)
)
) sub1
) SELECT * FROM BinPick
SELECT OWOR.docNum, WOR1.itemCode, plannedQty,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode
ORDER BY OWOR.docEntry) - (plannedQty - issuedQty) AS prevTotalNeeded,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode
ORDER BY OWOR.docEntry) AS runningTotalNeeded
FROM OWOR
JOIN WOR1
ON WOR1.docEntry = OWOR.docEntry
WHERE OWOR.status = 'R'
SELECT *
FROM (SELECT itemCode, whsCode, binCode, quantity,
SUM(quantity) OVER (PARTITION BY itemCode ORDER BY binCode) - quantity AS prevTotalQuantity,
SUM(quantity) OVER (PARTITION BY itemCode ORDER BY binCode) AS runningTotalQuantity
FROM (SELECT OIBQ.itemCode, OIBQ.whsCode, OBIN.binCode, SUM(OIBQ.onHandQty) AS quantity
FROM OIBQ
JOIN OBIN
ON OBIN.absEntry = OIBQ.binAbs
GROUP BY OIBQ.itemCode, OIBQ.whsCode, OBIN.binCode) TotalQuantity
) BINSTOCK
JOIN (SELECT OWOR.docNum, WOR1.itemCode, plannedQty,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode ORDER BY OWOR.docEntry) - (plannedQty - issuedQty) AS prevTotalNeeded,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode ORDER BY OWOR.docEntry) AS runningTotalNeeded
FROM OWOR
JOIN WOR1
ON WOR1.docEntry = OWOR.docEntry
WHERE OWOR.status = 'R') WOPICK
ON WOPICK.itemCode = BINSTOCK.itemCode
AND WOPICK.prevTotalNeeded <= BINSTOCK.runningTotalQuantity
AND WOPICK.runningTotalNeeded >= BINSTOCK.prevTotalQuantity
itemCode | whsCode | binCode | quantity | prevTotalQuantity | runningTotalQuantity | docNum | itemCode | plannedQty | prevTotalNeeded | runningTotalNeeded
:------- | :------ | :------ | :-------- | :---------------- | :------------------- | -----: | :------- | :--------- | :-------------- | :-----------------
A00001 | 98 | 98-A001 | 7.000000 | 0.000000 | 7.000000 | 901903 | A00001 | 12.000000 | 0.000000 | 12.000000
A00001 | 98 | 98-A002 | 6.000000 | 7.000000 | 13.000000 | 901903 | A00001 | 12.000000 | 0.000000 | 12.000000
A00001 | 98 | 98-A002 | 6.000000 | 7.000000 | 13.000000 | 901904 | A00001 | 17.000000 | 12.000000 | 29.000000
A00001 | 98 | 98-A003 | 12.000000 | 13.000000 | 25.000000 | 901904 | A00001 | 17.000000 | 12.000000 | 29.000000
A00001 | 98 | 98-A006 | 15.000000 | 25.000000 | 40.000000 | 901904 | A00001 | 17.000000 | 12.000000 | 29.000000
SELECT WOPICK.docNum, WOPICK.itemCode, WOPICK.plannedQty,
BINSTOCK.whsCode, BINSTOCK.binCode,
CASE WHEN WOPICK.prevTotalNeeded < BINSTOCK.prevTotalQuantity
AND WOPICK.runningTotalNeeded > BINSTOCK.runningTotalQuantity
THEN BINSTOCK.quantity
WHEN WOPICK.prevTotalNeeded >= BINSTOCK.prevTotalQuantity
AND WOPICK.runningTotalNeeded <= BINSTOCK.runningTotalQuantity
THEN WOPICK.neededQuantity
WHEN WOPICK.runningTotalNeeded <= BINSTOCK.runningTotalQuantity
THEN WOPICK.runningTotalNeeded - BINSTOCK.prevTotalQuantity
WHEN WOPICK.prevTotalNeeded >= BINSTOCK.prevTotalQuantity
THEN BINSTOCK.runningTotalQuantity - WOPICK.prevTotalNeeded
END AS quantityToPick
FROM (SELECT itemCode, whsCode, binCode, quantity,
SUM(quantity) OVER (PARTITION BY itemCode
ORDER BY binCode) - quantity AS prevTotalQuantity,
SUM(quantity) OVER (PARTITION BY itemCode
ORDER BY binCode) AS runningTotalQuantity
FROM (SELECT OIBQ.itemCode, OIBQ.whsCode, OBIN.binCode, SUM(OIBQ.onHandQty) AS quantity
FROM OIBQ
JOIN OBIN
ON OBIN.absEntry = OIBQ.binAbs
GROUP BY OIBQ.itemCode, OIBQ.whsCode, OBIN.binCode) TotalQuantity
) BINSTOCK
JOIN (SELECT OWOR.docNum, WOR1.itemCode, plannedQty, plannedQty - issuedQty AS neededQuantity,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode
ORDER BY OWOR.docEntry) - (plannedQty - issuedQty) AS prevTotalNeeded,
SUM(plannedQty - issuedQty) OVER (PARTITION BY WOR1.itemCode
ORDER BY OWOR.docEntry) AS runningTotalNeeded
FROM OWOR
JOIN WOR1
ON WOR1.docEntry = OWOR.docEntry
WHERE OWOR.status = 'R') WOPICK
ON WOPICK.itemCode = BINSTOCK.itemCode
AND WOPICK.prevTotalNeeded <= BINSTOCK.runningTotalQuantity
AND WOPICK.runningTotalNeeded >= BINSTOCK.prevTotalQuantity
docNum | itemCode | plannedQty | whsCode | binCode | quantityToPick
-----: | :------- | :--------- | :------ | :------ | :-------------
901903 | A00001 | 12.000000 | 98 | 98-A001 | 7.000000
901903 | A00001 | 12.000000 | 98 | 98-A002 | 5.000000
901904 | A00001 | 17.000000 | 98 | 98-A002 | 1.000000
901904 | A00001 | 17.000000 | 98 | 98-A003 | 12.000000
901904 | A00001 | 17.000000 | 98 | 98-A006 | 4.000000