如何使用 WHILE LOOP 将值添加到条件列表中,SQL Server 2008
How to use WHILE LOOP to add value to list with condition, SQL Server 2008
我有一个循环查询,场景如下:
- orderqty = 每个循环增加值 1
- runningstock = 每个循环减少值 1
- allocateqty = case when orderqty > 0 and runningstock > 0 then 1 else
0
- 循环直到 runningstock=0 或总分配=stockqty
查询:
DECLARE @RESULT TABLE (priority int,partcode nvarchar(50),orderqty int, runningstock int, allocateqty int)
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
DECLARE @STOCK TABLE(partcode nvarchar(50),stockqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
INSERT INTO @STOCK(partcode,stockqty)
VALUES('A',20);
DECLARE @allocateqty int=1
DECLARE @runningstock int=(SELECT stockqty FROM @stock)
WHILE @runningstock>=0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
SET @runningstock -=1
END
SELECT * FROM @Result
GO
结果:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 20 1
3 A 3 20 1
4 A 8 20 1
1 A 2 19 1
2 A 10 19 1
3 A 3 19 1
4 A 8 19 1
1 A 2 18 1
2 A 10 18 1
3 A 3 18 1
4 A 8 18 1
1 A 2 17 1
2 A 10 17 1
3 A 3 17 1
4 A 8 17 1
1 A 2 16 1
2 A 10 16 1
3 A 3 16 1
4 A 8 16 1
1 A 2 15 1
2 A 10 15 1
3 A 3 15 1
4 A 8 15 1
1 A 2 14 1
2 A 10 14 1
3 A 3 14 1
4 A 8 14 1
1 A 2 13 1
2 A 10 13 1
3 A 3 13 1
4 A 8 13 1
1 A 2 12 1
2 A 10 12 1
3 A 3 12 1
4 A 8 12 1
1 A 2 11 1
2 A 10 11 1
3 A 3 11 1
4 A 8 11 1
1 A 2 10 1
2 A 10 10 1
3 A 3 10 1
4 A 8 10 1
1 A 2 9 1
2 A 10 9 1
3 A 3 9 1
4 A 8 9 1
1 A 2 8 1
2 A 10 8 1
3 A 3 8 1
4 A 8 8 1
1 A 2 7 1
2 A 10 7 1
3 A 3 7 1
4 A 8 7 1
1 A 2 6 1
2 A 10 6 1
3 A 3 6 1
4 A 8 6 1
1 A 2 5 1
2 A 10 5 1
3 A 3 5 1
4 A 8 5 1
1 A 2 4 1
2 A 10 4 1
3 A 3 4 1
4 A 8 4 1
1 A 2 3 1
2 A 10 3 1
3 A 3 3 1
4 A 8 3 1
1 A 2 2 1
2 A 10 2 1
3 A 3 2 1
4 A 8 2 1
1 A 2 1 1
2 A 10 1 1
3 A 3 1 1
4 A 8 1 1
1 A 2 0 0
2 A 10 0 0
3 A 3 0 0
4 A 8 0 0
正确的应该是这样的:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 19 1
3 A 3 18 1
4 A 8 17 1
1 A 1 16 1
2 A 9 15 1
3 A 2 14 1
4 A 7 13 1
1 A 0 12 0
2 A 8 12 1
3 A 1 11 1
4 A 6 10 1
1 A 0 9 0
2 A 7 9 1
3 A 0 8 0
4 A 5 8 1
1 A 0 7 0
2 A 6 7 1
3 A 0 6 0
4 A 4 6 1
1 A 0 5 0
2 A 5 5 1
3 A 0 4 0
4 A 3 4 1
1 A 0 3 0
2 A 4 3 1
3 A 0 2 0
4 A 2 2 1
1 A 0 1 0
2 A 3 1 1
3 A 0 0 0
WHILE @runningstock>=0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @ORDER
SET @runningstock =@runningstock-1
END
这不是最好的方法,但你会得到预期的结果
DECLARE @RESULT TABLE (priority int,partcode nvarchar(50),orderqty int, runningstock int, allocateqty int)
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
DECLARE @STOCK TABLE(partcode nvarchar(50),stockqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
INSERT INTO @STOCK(partcode,stockqty)
VALUES ('A',20);
DECLARE @allocateqty int=1
DECLARE @runningstock int=(SELECT stockqty FROM @stock)
DECLARE @OutputTbl TABLE (orderqty INT)
WHILE @runningstock>0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 1
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 1
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 2
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 2
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 3
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 3
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 4
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 4
DELETE FROM @OutputTbl
print @runningstock
END
SELECT * FROM @Result
GO
如你所见,我将优先级分为 4 个步骤,每一步我都会降低
流水
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
订单数量
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 1
基于分配数量
OUTPUT inserted.allocateqty INTO @OutputTbl
您还可以遍历优先级并确保相应地更新订单数量。我会这样做:
DECLARE @allocatedqty int = 0
DECLARE @allocateqty int = 1
DECLARE @runningstock int = (SELECT stockqty FROM @stock)
WHILE @runningstock>=0
BEGIN
DECLARE @priority int
SELECT TOP 1 @priority = priority FROM @order ORDER BY priority ASC
WHILE @priority <= (SELECT MAX(priority) FROM @order)
BEGIN
DECLARE @orderqty int
SELECT @orderqty = orderqty - @allocatedqty FROM @order WHERE priority = @priority
SELECT @allocateqty = CASE WHEN @runningstock > 0 AND @orderqty > 0 THEN 1 ELSE 0 END
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT @priority,
partcode,
CASE WHEN @orderqty >= 0 THEN @orderqty ELSE 0 END AS orderqty,
@runningstock,
@allocateqty
FROM @order
WHERE priority = @priority
SET @priority += 1
SET @runningstock = @runningstock - @allocateqty
END
SET @allocatedqty += 1
IF (@runningstock <= 0) BREAK
END
SELECT * FROM @Result
GO
应尽可能避免在 sql 中循环。这将为您提供所描述的结果(除非您在倒计时中有 2 个错误):
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
DECLARE @runningstock INT = 20
;WITH CTE AS
(
SELECT
priority,
partcode,
orderqty,
@runningstock + 1 - priority runningstock,
sign(orderqty) allocateqty
FROM @ORDER
UNION ALL
SELECT
priority,
partcode,
orderqty - sign(orderqty),
runningstock - 4,
sign(orderqty - sign(orderqty))
FROM CTE
WHERE runningstock > 3
)
SELECT
priority, partcode, orderqty, runningstock, allocateqty
FROM CTE
ORDER BY runningstock desc, priority
结果:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 19 1
3 A 3 18 1
4 A 8 17 1
1 A 1 16 1
2 A 9 15 1
3 A 2 14 1
4 A 7 13 1
1 A 0 12 0
2 A 8 11 1
3 A 1 10 1
4 A 6 9 1
1 A 0 8 0
2 A 7 7 1
3 A 0 6 0
4 A 5 5 1
1 A 0 4 0
2 A 6 3 1
3 A 0 2 0
4 A 4 1 1
1 A 0 0 0
我有一个循环查询,场景如下:
- orderqty = 每个循环增加值 1
- runningstock = 每个循环减少值 1
- allocateqty = case when orderqty > 0 and runningstock > 0 then 1 else 0
- 循环直到 runningstock=0 或总分配=stockqty
查询:
DECLARE @RESULT TABLE (priority int,partcode nvarchar(50),orderqty int, runningstock int, allocateqty int)
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
DECLARE @STOCK TABLE(partcode nvarchar(50),stockqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
INSERT INTO @STOCK(partcode,stockqty)
VALUES('A',20);
DECLARE @allocateqty int=1
DECLARE @runningstock int=(SELECT stockqty FROM @stock)
WHILE @runningstock>=0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
SET @runningstock -=1
END
SELECT * FROM @Result
GO
结果:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 20 1
3 A 3 20 1
4 A 8 20 1
1 A 2 19 1
2 A 10 19 1
3 A 3 19 1
4 A 8 19 1
1 A 2 18 1
2 A 10 18 1
3 A 3 18 1
4 A 8 18 1
1 A 2 17 1
2 A 10 17 1
3 A 3 17 1
4 A 8 17 1
1 A 2 16 1
2 A 10 16 1
3 A 3 16 1
4 A 8 16 1
1 A 2 15 1
2 A 10 15 1
3 A 3 15 1
4 A 8 15 1
1 A 2 14 1
2 A 10 14 1
3 A 3 14 1
4 A 8 14 1
1 A 2 13 1
2 A 10 13 1
3 A 3 13 1
4 A 8 13 1
1 A 2 12 1
2 A 10 12 1
3 A 3 12 1
4 A 8 12 1
1 A 2 11 1
2 A 10 11 1
3 A 3 11 1
4 A 8 11 1
1 A 2 10 1
2 A 10 10 1
3 A 3 10 1
4 A 8 10 1
1 A 2 9 1
2 A 10 9 1
3 A 3 9 1
4 A 8 9 1
1 A 2 8 1
2 A 10 8 1
3 A 3 8 1
4 A 8 8 1
1 A 2 7 1
2 A 10 7 1
3 A 3 7 1
4 A 8 7 1
1 A 2 6 1
2 A 10 6 1
3 A 3 6 1
4 A 8 6 1
1 A 2 5 1
2 A 10 5 1
3 A 3 5 1
4 A 8 5 1
1 A 2 4 1
2 A 10 4 1
3 A 3 4 1
4 A 8 4 1
1 A 2 3 1
2 A 10 3 1
3 A 3 3 1
4 A 8 3 1
1 A 2 2 1
2 A 10 2 1
3 A 3 2 1
4 A 8 2 1
1 A 2 1 1
2 A 10 1 1
3 A 3 1 1
4 A 8 1 1
1 A 2 0 0
2 A 10 0 0
3 A 3 0 0
4 A 8 0 0
正确的应该是这样的:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 19 1
3 A 3 18 1
4 A 8 17 1
1 A 1 16 1
2 A 9 15 1
3 A 2 14 1
4 A 7 13 1
1 A 0 12 0
2 A 8 12 1
3 A 1 11 1
4 A 6 10 1
1 A 0 9 0
2 A 7 9 1
3 A 0 8 0
4 A 5 8 1
1 A 0 7 0
2 A 6 7 1
3 A 0 6 0
4 A 4 6 1
1 A 0 5 0
2 A 5 5 1
3 A 0 4 0
4 A 3 4 1
1 A 0 3 0
2 A 4 3 1
3 A 0 2 0
4 A 2 2 1
1 A 0 1 0
2 A 3 1 1
3 A 0 0 0
WHILE @runningstock>=0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @ORDER
SET @runningstock =@runningstock-1
END
这不是最好的方法,但你会得到预期的结果
DECLARE @RESULT TABLE (priority int,partcode nvarchar(50),orderqty int, runningstock int, allocateqty int)
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
DECLARE @STOCK TABLE(partcode nvarchar(50),stockqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
INSERT INTO @STOCK(partcode,stockqty)
VALUES ('A',20);
DECLARE @allocateqty int=1
DECLARE @runningstock int=(SELECT stockqty FROM @stock)
DECLARE @OutputTbl TABLE (orderqty INT)
WHILE @runningstock>0
BEGIN
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 1
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 1
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 2
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 2
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 3
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 3
DELETE FROM @OutputTbl
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
OUTPUT inserted.allocateqty INTO @OutputTbl
SELECT priority,
partcode,
orderqty,
@runningstock,
CASE WHEN @runningstock > 0 AND orderqty > 0 THEN 1 ELSE 0 END
FROM @order
WHERE priority = 4
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 4
DELETE FROM @OutputTbl
print @runningstock
END
SELECT * FROM @Result
GO
如你所见,我将优先级分为 4 个步骤,每一步我都会降低 流水
SELECT @runningstock -= SUM(orderqty) FROM @OutputTbl
订单数量
UPDATE @order SET orderqty -= (SELECT SUM(orderqty) FROM @OutputTbl) WHERE priority = 1
基于分配数量
OUTPUT inserted.allocateqty INTO @OutputTbl
您还可以遍历优先级并确保相应地更新订单数量。我会这样做:
DECLARE @allocatedqty int = 0
DECLARE @allocateqty int = 1
DECLARE @runningstock int = (SELECT stockqty FROM @stock)
WHILE @runningstock>=0
BEGIN
DECLARE @priority int
SELECT TOP 1 @priority = priority FROM @order ORDER BY priority ASC
WHILE @priority <= (SELECT MAX(priority) FROM @order)
BEGIN
DECLARE @orderqty int
SELECT @orderqty = orderqty - @allocatedqty FROM @order WHERE priority = @priority
SELECT @allocateqty = CASE WHEN @runningstock > 0 AND @orderqty > 0 THEN 1 ELSE 0 END
INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty)
SELECT @priority,
partcode,
CASE WHEN @orderqty >= 0 THEN @orderqty ELSE 0 END AS orderqty,
@runningstock,
@allocateqty
FROM @order
WHERE priority = @priority
SET @priority += 1
SET @runningstock = @runningstock - @allocateqty
END
SET @allocatedqty += 1
IF (@runningstock <= 0) BREAK
END
SELECT * FROM @Result
GO
应尽可能避免在 sql 中循环。这将为您提供所描述的结果(除非您在倒计时中有 2 个错误):
DECLARE @ORDER TABLE(priority int,partcode nvarchar(50),orderqty int)
INSERT INTO @ORDER (priority,partcode,orderqty)
VALUES(1,'A',2),
(2,'A',10),
(3,'A',3),
(4,'A',8);
DECLARE @runningstock INT = 20
;WITH CTE AS
(
SELECT
priority,
partcode,
orderqty,
@runningstock + 1 - priority runningstock,
sign(orderqty) allocateqty
FROM @ORDER
UNION ALL
SELECT
priority,
partcode,
orderqty - sign(orderqty),
runningstock - 4,
sign(orderqty - sign(orderqty))
FROM CTE
WHERE runningstock > 3
)
SELECT
priority, partcode, orderqty, runningstock, allocateqty
FROM CTE
ORDER BY runningstock desc, priority
结果:
priority partcode orderqty runningstock allocateqty
1 A 2 20 1
2 A 10 19 1
3 A 3 18 1
4 A 8 17 1
1 A 1 16 1
2 A 9 15 1
3 A 2 14 1
4 A 7 13 1
1 A 0 12 0
2 A 8 11 1
3 A 1 10 1
4 A 6 9 1
1 A 0 8 0
2 A 7 7 1
3 A 0 6 0
4 A 5 5 1
1 A 0 4 0
2 A 6 3 1
3 A 0 2 0
4 A 4 1 1
1 A 0 0 0