Использование рекурсивных CTE для l oop через таблицу - PullRequest
0 голосов
/ 14 апреля 2020

Мне нужна помощь, чтобы закрыть кусок кода, где, я думаю, я уже добился значительного прогресса. После запуска SP следующая таблица заполняется, как указано ниже:

Id       Counter    Date  RecQty    RecAmt    IssQty   IssAmt   ClQty        ClAmt            ClRate
1        0         Jan-1                                         100        $20,000            $200
2        1         Jan-2   10        $2,100     5       [A]      105         [X]                [P]
3        2         Jan-3   8         $1,600     2       [B]      111         [Y]                [Q]
4        3         Jan-4   20        $4,400     10      [C]      121         [Z]                [R]

Схема таблицы выглядит следующим образом: Столбец id имеет тип int и просто увеличивает каждую строку на 1. Столбец счетчика имеет тип int и просто увеличивает каждую строку на 1. Полученное количество (RecQty), полученное количество (RecAmt), выпущенное количество (IssQty) являются десятичными типа и являются постоянными значениями, которые останутся неизменными при любых операциях в таблице.

Количество закрытия (ClQty) - это количество закрытия предыдущего дня ClQty + полученное количество текущего дня (RecQty) - количество выпущенных текущих дней (IssQty). Так что для января-2 это (100 + 10 -5). Поскольку все базовые значения являются константами, этот столбец не является проблемой для вычисления.

Теперь для каждой строки в таблице мне нужно вычислить и вставить значения в 3 столбца - IssAmt, ClAmt и ClRate. Процесс определения каждой суммы выглядит следующим образом:

  1. IssAmt - Возьмите курс закрытия предыдущего дня (ClRate) и умножьте его на IssQty текущего дня. Таким образом, для января-2 этот результат будет равен 1 000 долл. США - получено как 200 долл. США (январь-1: прогноз за предыдущий день) 5 раз (январь-2).
  2. ClAmt - принять сумму закрытия предыдущего дня (ClAmt) добавить сумму полученного текущего дня (RecAmt) и вычесть выданную сумму за текущий день (как вычислено в пункте 1). Таким образом, для января-2 правильный результат будет 21 100 долл. США, то есть 20 000 долл. США (1 января) ClAmt + 2100 долл. США - 1000
  3. ClRate - возьмите сумму закрытия текущего дня (ClAmt), полученную в точке 2, и разделите ее на количество закрытия текущего дня (ClQty). Таким образом, для января-2 правильная цена закрытия будет составлять 21 100 долл. США / 105 = 200,95 долл. США

Для января-3 будут использоваться результаты января-2 - и т. Д. И т. Д.

Код таблицы выглядит следующим образом:

CREATE TABLE [Auto].[IronOreTbl](
    [Id] [int] NULL,
    [Counter] [int] NULL,
    [TDate] [date] NOT NULL,
    [RecQty] [decimal](16, 2) NULL,
    [RecAmt] [decimal](16, 2) NULL,
    [IssQty] [decimal](16, 2) NULL,
    [IssAmt] [decimal](16, 2) NULL,
    [ClQty] [decimal](16, 2) NULL,
    [ClAmt] [decimal](16, 2) NULL,
    [ClRate] [decimal](16, 2) NULL

) ON [PRIMARY]
GO

INSERT INTO [Auto].[IronOreTbl]
    ([Id],[Counter],[TDate],[RecQty],[RecAmt],[IssQty],[IssAmt],[ClQty],[ClAmt],[ClRate])
    VALUES
    (1,0,'2019-01-01',NULL,NULL,NULL,NULL,100,20000,200),
    (2,1,'2019-01-02',10,2100,5,NULL,105,NULL,NULL),
    (3,2,'2019-01-03',8,1600,2,NULL,111,NULL,NULL),
    (4,3,'2019-01-04',20,2400,10,NULL,121,NULL,NULL)

Теперь мои попытки решить эту проблему. Я использовал рекурсивную структуру CTE, и я излагаю свой код ниже

;WITH ClAmtCTE AS

    (
    SELECT
        Id,RecQty,RecAmt,IssQty,ClQty,ClAmt,ClRate
        ,EffRate = ClRate
        ,CumHoldVal= ClAmt
        --CAST(ClAmt AS decimal(16,2))
        ,CumClRt=CAST(ClRate AS decimal(16,2))
        ,[Counter]
    FROM
        [Auto].IronOreTbl
    WHERE
        Id=1 

    UNION ALL

    SELECT
        C2.Id,C2.RecQty,c2.RecAmt,C2.IssQty,C2.ClQty,C2.ClAmt,c2.ClRate,
        EffRate = (SELECT CumClRt WHERE C2.ID=C2.[Counter]+1), 
        CumRN = 
        CAST(
            (
            CumHoldVal+ISNULL(C2.RecAmt,0)-
            (EffRate)*ISNULL(C2.IssQty,0)
            )
        AS decimal(16,2)
        ),
        CumClRt=CAST(CumHoldVal/C2.ClQty AS decimal(16,2)),
        C2.[Counter],

    FROM
        [Auto].IronOreTbl C2 
    INNER JOIN ClAmtCTE C1 ON C1.Id = C2.[Counter]

Мой пример кода дает мне следующий вывод. (Переменная CumHolVal содержит суммы для столбца ClAmt, тогда как переменная CumClRate содержит суммы для столбца ClRate. Я не заполнил столбец IssAmt в приведенном ниже извлечении, поскольку его KRA предназначен для правильного вычисления ClAmt и ClRate)

   Id    Counter    Date  RecQty    RecAmt    IssQty   IssAmt   ClQty        ClAmt            ClRate
    1        0         Jan-1                                     100        $20,000            $200
    2        1         Jan-2   10    $2,100     5       [A]      105        $21,100            $190.48
    3        2         Jan-3   8     $1,600     2       [B]      111        $22,300            $190.09
    4        3         Jan-4   20    $4,400     10      [C]      121        $24,795.2          $184.30

Вот мои наблюдения по полученным результатам. ClAmt за январь-2 (21 100 долл. США) верен - последующие строки - нет. Неточность ClRate вычисляется путем неправильного определения ClAmt предыдущего дня (а не того же дня) и правильного деления его на ClQty того же дня. Я в своем уме пытаюсь это исправить. Если эта часть может быть исправлена, я чувствую, что код будет работать нормально. Чтобы усилить мою точку зрения, показатель ЯР-2 оценивается в 20 000 долл. США (ЯН-1: НЕПРАВИЛЬНО: неверно) / 105 (ЯНВ-2: ОБЗОР: правильно) = 190,48. Правильный расчет должен составлять 21 100 долл. США (январь-2. CLAmt: правильно) / 105 (январь-2 CLQty: правильно) = 200,95

Это поставило меня на колени. Я надеюсь, что у кого-то есть терпение go через этот пост, способ указать на мою ошибку и доброту сердца, чтобы ответить ......

...