I'm trying to estimate a new scrap rate (loss factor) in a production line using SQL.
Basically, there are several operation in one machine, with qty in and qty out for each one of the operation.
The following operation has, as qty in, the qty out of the previous operation.
And this scrap rate (loss factor) needs to be carry over the operation.
So, operation 1 will have qty out / qty in from operation 1 = scrap rate 1; operation 2 has qty out / qty in * scrap rate 1; and so on.
I know I can use "exp(sum(log(column)) OVER (ORDER BY column))" to get the overall, lets say machine scrap rate, but I need to have an cumulative per machine-operation level.
Hope the image attached can explain better the outcome.
I'm struggling to calculate the column G (OutFactorAccumulated) in the image. Hope someone can help me.
Data and expected results example
calculate cumulative product
CodePudding user response:
I think you are most of the way there.
The final step is simply to take the OutfactorAccumulated column, and do a similar windowed function over it to calculate the next column e.g.,
MIN(OutFactorAccumulated) OVER (PARTITION BY Machine)
.
Note also that the other windowed function (the SUM) should also have a PARTITION BY Machine
in the window to ensure that each machine only uses its own data.
Here is a db<>fiddle with the example code below in SQL Server/T-SQL.
- The last CTE 'MachineData_with_ExpQtyOut` is the one that has the windows MIN function to do the calculation.
- In the Fiddle I have also added a second machine B1 with some data I made up - to demonstrate it works with multiple machines.
(Note lots of CAST AS decimal(14,10) to match your data - there's probably a better way to do this).
CREATE TABLE #MachData (Machine nvarchar(10), Operation int, QtyIn int, QtyOut int, PRIMARY KEY (Machine, Operation));
INSERT INTO #MachData (Machine, Operation, QtyIn, QtyOut) VALUES
(N'A1', 1, 100, 100),
(N'A1', 2, 100, 95),
(N'A1', 3, 95, 95),
(N'A1', 4, 95, 94),
(N'A1', 5, 94, 86),
(N'A1', 6, 86, 66),
(N'A1', 7, 66, 66),
(N'A1', 8, 66, 66),
(N'A1', 9, 66, 66);
WITH MachData_with_Factors AS
(SELECT Machine,
Operation,
QtyIn,
QtyOut,
CAST(1 - CAST(QtyOut AS decimal(14,10))/CAST(QtyIn AS decimal(14,10)) AS decimal(14,10)) AS LossFactor,
CAST(CAST(QtyOut AS decimal(14,10))/CAST(QtyIn AS decimal(14,10)) AS decimal(14,10)) AS OutFactor
FROM #MachData
),
MachineData_with_Acc AS
(SELECT *,
CAST(exp(SUM(log(OutFactor)) OVER (PARTITION BY Machine ORDER BY Operation)) AS decimal(14,10)) AS OutFactorAccumulated
FROM MachData_with_Factors
),
MachineData_with_ExpQtyOut AS
(SELECT *,
CAST(OutFactorAccumulated * 100.0 / MIN(OutFactorAccumulated) OVER (PARTITION BY machine) AS decimal(14,10)) AS NewExpectedQtyOut
FROM MachineData_with_Acc
)
SELECT *
FROM MachineData_with_ExpQtyOut
ORDER BY Machine, Operation;
Results are as below
Machine Operation QtyIn QtyOut LossFactor OutFactor OutFactorAccumulated NewExpectedQtyOut
------------------------------- ---------------------------------------------------------------------------
A1 1 100 100 0.0000000000 1.0000000000 1.0000000000 151.5151515152
A1 2 100 95 0.0500000000 0.9500000000 0.9500000000 143.9393939394
A1 3 95 95 0.0000000000 1.0000000000 0.9500000000 143.9393939394
A1 4 95 94 0.0105263158 0.9894736842 0.9400000000 142.4242424242
A1 5 94 86 0.0851063830 0.9148936170 0.8600000000 130.3030303030
A1 6 86 66 0.2325581395 0.7674418605 0.6600000000 100.0000000000
A1 7 66 66 0.0000000000 1.0000000000 0.6600000000 100.0000000000
A1 8 66 66 0.0000000000 1.0000000000 0.6600000000 100.0000000000
A1 9 66 66 0.0000000000 1.0000000000 0.6600000000 100.0000000000