Круговая зависимость ад. Использовать значение из предыдущей строки в текущей - PullRequest
1 голос
/ 17 января 2020

Я хочу рассчитать спецификацию и застрял в расчете некоторых атрибутов.

Это ссылка на листы Google со всеми данными и необходимыми формулами

У меня есть
Количество в наличии (@QOH) - 95
Страховой запас (@SS) - 58

DECLARE @qoh INT = 95
      , @ss  INT = 58
      , @eoq INT = 96;

CREATE TABLE #data
(
     PartId INT
  ,  SalesOrderQty INT
  , SalesDate     DATE
);

INSERT INTO #data (PartId
                 , SalesOrderQty
                 , SalesDate)
VALUES (1, 75, '20190101')
     , (1, 100, '20190201')
     , (1, 115, '20190301')
     , (1, 95, '20190401')
     , (1, 132, '20190501');

Мне нужно вычислить 3 объекта:

  • @Supply - если это первая запись (20190101), то @QOH-@SS-#data.SalesOrderQty,
    в противном случае (Previous month)@RecommendedQty - #data.SalesOrderQty

  • @EOQMultiplier - CEILING(ABS(@Supply/@eoq))

  • @RecommendedQty - если @Supply <= 0, то @EOQMultiplier * @eoq ИЛИ @Supply

Ожидаемые данные

|--------|----------|-------|---------------|-----------------|
| PartId | Date     |Supply | EOQMultiplier | RecommendedQty  |
|--------|----------|-------|---------------|-----------------|
| 1      | 20190101 | -38   | 1             | 96              |
| 1      | 20190201 | -4    | 1             | 96              |
| 1      | 20190301 | -19   | 1             | 96              |
| 1      | 20190401 | 1     | 1             | 1               |
| 1      | 20190501 | -131  | 2             | 192             |
|--------|----------|-------|---------------|-----------------|

Проблема, с которой я сталкиваюсь, заключается в том, что @Supply и @RecommendedQty ссылаются друг на друга, а мой решение становится слишком сложным и хакерским, так как SQL Server 2008 R2 не поддерживает некоторые полезные функции WINDOW

1 Ответ

1 голос
/ 17 января 2020

Это один из немногих случаев, когда я бы рекомендовал решение на основе курсора. Он плохо масштабируется, поэтому, если ваши данные большие, это плохой выбор, но, по крайней мере, он будет делать то, что вам нужно, вполне понятным способом

DECLARE @qoh INT = 95
      , @ss  INT = 58
      , @eoq INT = 96;

CREATE TABLE #data
(
     PartId INT
  ,  SalesOrderQty INT
  , SalesDate     DATE
);

INSERT INTO #data (PartId
                 , SalesOrderQty
                 , SalesDate)
VALUES (1, 75, '20190101')
     , (1, 100, '20190201')
     , (1, 115, '20190301')
     , (1, 95, '20190401')
     , (1, 132, '20190501');

;with cteOrdered as (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY PartID ORDER BY  SalesDate) as RowNum 
    FROM #data 
)
SELECT *, @QOH-@SS-SalesOrderQty as Supply, 1 as EOQMultiplier, @QOH as RecommendedQty
INTO #DataTemp 
FROM cteOrdered

DECLARE @PartId INT
DECLARE  @SalesOrderQty int
DECLARE  @SalesDate DATE 
DECLARE  @RowNum int
DECLARE  @Supply int
DECLARE  @EOQMultiplier int
DECLARE  @RecommendedQty int
DECLARE  @PrevRecQty int

DECLARE curMonth CURSOR FOR   
SELECT PartId , SalesOrderQty , SalesDate , RowNum , Supply , EOQMultiplier, RecommendedQty 
FROM #DataTemp
ORDER BY PartID, RowNum;

OPEN curMonth  

FETCH NEXT FROM curMonth   
INTO @PartId , @SalesOrderQty , @SalesDate , @RowNum , @Supply , @EOQMultiplier, @RecommendedQty

WHILE @@FETCH_STATUS = 0  
BEGIN  
    IF (@RowNum = 1) BEGIN --No prior month
        SET @Supply = @QOH - @SS - @SalesOrderQty
    END ELSE BEGIN
        SET @Supply = @PrevRecQty - @SalesOrderQty 
    END
    SET @EOQMultiplier = CEILING(ABS(@Supply*1.0/@eoq))
    if (@Supply <= 0) BEGIN
        SET @RecommendedQty = @EOQMultiplier * @eoq 
    END ELSE BEGIN 
        SET @RecommendedQty = @Supply
    END

    SET @PrevRecQty = @RecommendedQty

    UPDATE #DataTemp 
    SET Supply = @Supply, EOQMultiplier = @EOQMultiplier, RecommendedQty= @RecommendedQty
    WHERE PartId = @PartId AND RowNum = @RowNum

    FETCH NEXT FROM curMonth   
    INTO @PartId , @SalesOrderQty , @SalesDate , @RowNum , @Supply , @EOQMultiplier, @RecommendedQty
END   
CLOSE curMonth;  
DEALLOCATE curMonth; 

SELECT * FROM #DataTemp 

DROP TABLE #data 
DROP TABLE #DataTemp 
...