Sql server SQL查询将产品数量按顺序拆分为特定的常量阈值数量?

Sql server SQL查询将产品数量按顺序拆分为特定的常量阈值数量?,sql-server,Sql Server,有一份产品清单和数量。每个产品数量必须划分为特定的常量 我试过使用给定的列表,如果产品数量大于常量,结果很好。当产品数量小于常数时,我无法推导出逻辑。固定产品数量为650 SortOrder ProductCode Quantity 1 PC1 1400 2 PC2 4500 3 PC3 1500 下面给出的代码适用于此列表 SortOrder ProductID Quant

有一份产品清单和数量。每个产品数量必须划分为特定的常量

我试过使用给定的列表,如果产品数量大于常量,结果很好。当产品数量小于常数时,我无法推导出逻辑。固定产品数量为650

SortOrder   ProductCode Quantity
1           PC1         1400
2           PC2         4500
3           PC3         1500
下面给出的代码适用于此列表

SortOrder   ProductID   Quantity
1           PC1         650
1           PC1         650
1           PC1         100
2           PC2         550
2           PC2         650
2           PC2         650
2           PC2         650
2           PC2         650
2           PC2         650
2           PC2         650
2           PC2         50
3           PC3         600
3           PC3         650
3           PC3         250
但问题是,如果产品数量小于常量值

SortOrder   ProductCode Quantity
1           PC1         400
2           PC2         500
3           PC3         1300
4           PC4         300
5           PC5         500
结果应该是

SortOrder   ProductCode Quantity    Shift
1           PC1         400         A
2           PC2         250         A
2           PC2         250         B
3           PC3         400         B
3           PC3         650         C
3           PC3         250         A
4           PC4         300         A
5           PC5         100         A
5           PC5         400         B

每次移位的总和应等于常量


请在这方面帮助我。

我用两个示例测试了它并获得了预期的输出,我使用递归CTE来获得补偿量,如果您想让我对代码的特定部分进行更深入的解释,请告诉我

DECLARE @const INT = 650;

SELECT       sortorder
           , productid
           , c.val
  FROM       #Temp_ProductQtyOrderList   AS l
 CROSS APPLY (   SELECT ROW_NUMBER() OVER (ORDER BY o.object_id) AS m
                   FROM sys.all_objects o
                   ) AS mult
 CROSS APPLY (SELECT quantity / (mult.m * @const) AS val) AS a
 CROSS APPLY (   SELECT CASE WHEN quantity < @const THEN quantity
                             WHEN val = 0 THEN quantity - @const * (mult.m - 1)
                             ELSE @const
                        END AS val) AS c
 WHERE       mult.m <= quantity / @const + 1 AND c.val > 0;
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…

如果结果数量不符合常量,则从下一个产品中获取剩余数量。对于PC1,将1400拆分为650650100。对于第三行,100不等于650。因此,从下一个产品PC2获得剩余的550条。如果您为所有需要的对象提供INSERT语句,而不是table+DDL语句中的数据,那么回答您的问题会更容易。查询本身INSERT语句和DDL语句可用。有点不清楚。如果常数=100,是否将450拆分为100+100+100+100+50?如果const=500,那么值应该保持在450?是的,你是对的。根据常数,我们必须将其拆分。如果常数=500,则数量将为450当前产品+50下一产品谢谢您的回答,但目标尚未实现。请考虑以下的“产品编号1 PC1 400,2 PC2 500 500 3 PC3 1300 4 PC4 300 300 5 PC500”您的意思是什么?谢谢您的回答。但是编辑了问题,请检查结果如何。谢谢你的回答。但是编辑了问题,请检查结果应该如何。@Vinoth我更新了答案,请不要再这样做了,编辑问题以改进解释与编辑问题以添加新要求之间存在巨大差异。。。另外,你故意破坏了你自己的问题,删除了有用的信息,因为你的定义和当前的方法我真的很抱歉。但结果仍然没有出现。我用这种方法和你的样本数据得到的唯一区别是我提到的关于重复移位的数据,你能比结果没有出现更具体一些吗?如果你将移位公式替换为CHAR64+isnullnullifu\u按OD排列顺序,当数量