Я протестировал его с обоими образцами и получил ожидаемый результат, я использовал рекурсивный CTE для получения величины компенсации, дайте мне знать, если вы хотите, чтобы я написал более подробное объяснение определенной части кода.
DECLARE @Const INT = 650
;WITH nums AS (
SELECT 1 as num
UNION ALL
SELECT num + 1 FROM nums WHERE num < 100
), compensation AS (
SELECT *, 0 as Compensation, SortOrder as OD
FROM #Temp_ProductQtyOrderList t
WHERE SortOrder = 1
UNION ALL
SELECT t.*, CASE WHEN c.Quantity - Compensation < 0 THEN ABS(c.Quantity - Compensation) ELSE @Const - ((c.Quantity - Compensation)%@const) END,
CASE WHEN c.Quantity - Compensation < 0 THEN c.OD ELSE c.SortOrder END
FROM #Temp_ProductQtyOrderList t
JOIN compensation C ON c.SortOrder = t.SortOrder - 1
), split1 AS (
SELECT CASE compensation WHEN 0 THEN 0 ELSE 1 END + num rn, b.*, t.SortOrder as OD
FROM compensation t
CROSS APPLY (
VALUES(t.SortOrder, t.ProductID, @const)
) b (SortOrder, ProductCode, Quantity)
join nums ON num <= (t.Quantity-compensation)/@const
UNION ALL
SELECT 1, t.SortOrder, t.ProductID, CASE WHEN Quantity > compensation THEN compensation ELSE Quantity END, OD
FROM compensation t
WHERE compensation > 0
UNION ALL
SELECT CASE compensation WHEN 0 THEN 0 ELSE 1 END + (t.Quantity-compensation)/@const + 1, t.SortOrder, t.ProductID, (t.Quantity-compensation)%@const, sortorder
FROM compensation t
WHERE (t.Quantity-compensation)%@const > 0
)
SELECT SortOrder, RN, ProductCode, Quantity, CHAR(64 + DENSE_RANK() OVER (ORDER BY OD, CASE WHEN Quantity<@Const OR SortOrder<> OD THEN 999 ELSE rn END)) Shift
FROM split1
ORDER BY SortOrder, rn, ProductCode
PS Ваш собственный образец не соответствует вашему требованию:
сумма каждой смены должна быть равна постоянному значению
Я не нашел разумных критериев для повторения сдвигов A и B, поэтому он вернет сдвиги A, B, C, D и E для этого образца ввода ...