2015-06-17 7 views
3

У меня есть запрос с 3 переменными таблицами: @result, @order и @stock. Логика - это количество акций, которое должно быть выделено за счет лотов (здесь i set = 1) ко всему порядку, основанному на приоритете (FIFO). кол-во акций должно быть выделено до нуля, а allocateqty должно < = orderqty. проблема в одном из ордеров, его allocateqty над orderqty (priority = 7), а другие правильные.Как исправить эту логику?

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',10), 
(2,'A',50), 
(3,'A',10), 
(4,'A',40), 
(5,'A',3), 
(6,'A',5), 
(7,'A',11), 
(8,'A',10), 
(9,'A',10), 
(10,'A',10); 


INSERT INTO @STOCK(partcode,stockqty) 
VALUES('A',120) 

IF (SELECT SUM(orderqty)FROM @ORDER)<(SELECT stockqty FROM @STOCK) 
BEGIN 
INSERT INTO @RESULT(priority,partcode,orderqty,allocateqty) 
SELECT priority, partcode,orderqty,orderqty 
FROM @ORDER 
END 
ELSE 
BEGIN 
DECLARE @allocatedqty int = 0 
DECLARE @Lotsize int=1 
DECLARE @allocateqty int = @Lotsize 
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 @Lotsize 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 += @allocateqty 
    IF (@runningstock <= 0) BREAK 
END 
END 
select * from @RESULT where priority=7; 

SELECT priority, 
sum(allocateqty) as allocated 
from @RESULT 
group by priority 

результат:

enter image description here

+0

Какую версию сервера sql вы используете? мы можем удалить использование 'while' все вместе – ughai

+0

@ughai, sql server 2008 R2 – Sokea

ответ

3

моя репутация не достигнет 50 так косяк добавить комментарий.

Вы сказали, что ваш другой заказ верен, тогда приоритет = 7 также правильный. вы можете сравнить приоритеты 2 и 4 с 7. это то же самое. я думаю, что все ваши петли для orderqty достигают только 10 раз, где приоритет 7 получили 11 так он оставил 1.

Либо все правильно или все не так = х

EDIT:

Привет , Я нашел ответ.

Изменить

SET @allocatedqty += @allocateqty 

в

SET @allocatedqty += 1 

, потому что при использовании SET @allocatedqty += @allocateqty, последний заказ @allocateqty является 0, то он всегда будет делать @allocatedqty = 0, то она не будет увеличиваться.

Надеюсь, это действительно поможет вам.

EDIT на основе @Jesuraja данного ответа должно быть:

SET @allocatedqty += @Lotsize 
+0

все приоритеты, кроме приоритета = 7, являются правильными. Я также думаю о цикле только 10 раз (общее количество приоритетов) и приоритет = 7 цикл до 11, но как это исправить? – Sokea

+0

Я не уверен, чего вы пытаетесь достичь? можете ли вы подробно объяснить, что вы хотите? у вас есть 10 заказов и только 120 штук – HJK

+0

10 заказов с общим количеством qty = 159, stockqty = 120, поэтому мне нужно распределять/делиться акциями ко всем заказам каждый раз = lotsize = 1 до нулевого запаса. порядок qty должен <= выделять qty при распределении на основе приоритета (FIFO). – Sokea

0

Как я не совсем уверен, что вы пытаетесь достичь с помощью записей, которые установят ваш запас 0 или за я просто не могу представить это , Но это намного лучше, чем выполнять все ваши заказы в цикле. Может быть, вы захотите заменить свой цикл.

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',10),(2,'A',50),(3,'A',10),(4,'A',40),(5,'A',3),(6,'A',5),(7,'A',11),(8,'A',10),(9,'A',10),(10,'A',10); --your orders 
VALUES (1,'A',1),(2,'A',2),(3,'A',3),(4,'A',4),(5,'A',5),(6,'A',6),(7,'A',7),(8,'A',8),(9,'A',9),(10,'A',10); 

INSERT INTO @STOCK(partcode,stockqty) 
--VALUES('A',50) -- your stock 
VALUES('A',50) 

IF (SELECT SUM(orderqty) FROM @ORDER)<(SELECT stockqty FROM @STOCK) 
BEGIN 
    INSERT INTO @RESULT(priority,partcode,orderqty,allocateqty) 
    SELECT priority, partcode,orderqty,orderqty 
    FROM @ORDER 
END 
ELSE 
BEGIN 
      ;WITH dat AS(
       SELECT s.partcode, s.stockqty, o.priority, o.orderqty, 
        ROW_NUMBER() OVER(PARTITION BY s.partcode ORDER BY o.priority DESC) as runningOrder 
       FROM @Stock as s 
       INNER JOIN @ORDER as o 
         ON s.partcode = o.partcode 
      ) 
      INSERT INTO @RESULT(priority,partcode,orderqty,runningstock,allocateqty) 
       SELECT d1.priority, d1.partcode, d1.orderqty, 
        d1.stockqty - SUM(d2.orderqty) OVER(PARTITION BY d1.runningOrder) as runningstock, 
        CASE WHEN d1.stockqty - SUM(d2.orderqty) OVER(PARTITION BY d1.runningOrder) > 0 AND d1.orderqty > 0 THEN 1 ELSE 0 END 
       FROM dat as d1 
       INNER JOIN dat as d2 
         ON d1.partcode = d2.partcode 
         AND d1.runningOrder >= d2.runningOrder 

END 
select * from @RESULT where priority=7; 

SELECT priority, 
sum(allocateqty) as allocated 
from @RESULT 
group by priority 
+0

u можете попробовать выбрать * из @RESULT из своего кода удалить приоритет = 7, тогда вы поймете, чего он хочет – HJK

+0

mh. Думаю, я этого не понимаю. Он просто хочет вычесть заказы из акций на основе их приоритета. Не так ли? Что он хочет сделать, если у него есть запас 10 и порядок 11. Если запас будет оставлен до 10? или он должен идти до -1? Если этот порядок будет пропущен, а следующий порядок должен быть вычтен вместо этого? – Ionic

+0

@lonic, в случае акции = 10 и order = 11 => allocate qty = 10 в случае, если есть только 1 порядок. но если есть много ордеров, то распределение должно делиться qty = лотифицировать каждый цикл до нулевого запаса, чтобы убедиться, что все заказы получают запас. allocate qty должно <= order qty. – Sokea

Смежные вопросы