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