Выполнить рекурсивный расчет на основе расчета предыдущих дней - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть таблица dbo.TrueMarginCalc, которую мне нужно выполнить, чтобы рассчитать взвешенную стоимость на основе даты.У меня также есть эта таблица, которая иллюстрирует, что мне нужно делать.Таблица в базе данных выглядит следующим образом.

На изображении ниже эта таблица отсортирована по [Дата] ASC, и я вычисляю первый экземпляр следующим образом:

enter image description here

Затем мне нужно рекурсивно вычислить это снова, используя «Взвешенную истинную стоимость» предыдущего дня и т. Д. И т. Д .:

enter image description here enter image description here

Мой код таков:

CREATE TABLE dbo.TrueMarginCalc 
(
    [WHS] varchar(3),
    [PRODUCT] varchar(5),
    [TRANS DATE] DATE,
    [RECEIPTS] INT,
    [TRUE COST] NUMERIC(18,8),
    [RUNNING_SALES] INT,
)

INSERT INTO dbo.TrueMarginCalc 
SELECT 
'350','54710','2018-09-06',42,0.7128,52   UNION ALL SELECT
'350','54710','2018-09-07',42,0.7154,61   UNION ALL SELECT
'350','54710','2018-09-08',42,0.715 ,42   UNION ALL SELECT
'350','54710','2018-09-10',0    ,0  ,37   UNION ALL SELECT
'350','54710','2018-09-11',42,0.7124,44   UNION ALL SELECT
'350','54710','2018-09-12',42,0.7125,42   UNION ALL SELECT
'350','54710','2018-09-13',42,0.7147,77   UNION ALL SELECT
'350','54710','2018-09-14',0    ,0  ,35   UNION ALL SELECT
'350','54710','2018-09-15',42,0.7123,47   UNION ALL SELECT
'350','54710','2018-09-17',0    ,0  ,22   UNION ALL SELECT
'350','54710','2018-09-18',42,0.7183,45   UNION ALL SELECT
'350','54710','2018-09-19',42,0.71  ,42   UNION ALL SELECT
'350','54710','2018-09-20',42,0.7124,56   UNION ALL SELECT
'350','54710','2018-09-21',0    ,0  ,10   UNION ALL SELECT
'350','54710','2018-09-22',42,0.7124,43   UNION ALL SELECT
'350','54710','2018-09-24',0    ,0  ,0    UNION ALL SELECT
'350','54710','2018-09-25',42,0.71  ,41   UNION ALL SELECT
'350','54710','2018-09-26',42,0.71  ,54    

select *, (Running_Sales*[TRUE COST])/NULLIF(Running_Sales,0) As [Weighted True Cost] 
FROM dbo.TrueMarginCalc order by [TRANS DATE]

Все, что нужно сделать, - это рассчитать средневзвешенную истинную стоимость за первый день.Требуется ли для выполнения этого в T-SQL какой-либо курсор или рекурсия?

;
WITH CTE AS (

select ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]) AS RNK, WHS,PRODUCT,[TRANS DATE], [RECEIPTS], [TRUE COST], RUNNING_SALES
, CAST((Running_Sales*[TRUE COST])/NULLIF(Running_Sales,0) AS MONEY) As [Weighted True Cost] FROM dbo.TrueMarginCalc 

UNION ALL

select ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]) AS RNK, WHS,PRODUCT,[TRANS DATE], [RECEIPTS], [TRUE COST], RUNNING_SALES
, CAST((Receipts*[TRUE COST])+([Weighted True Cost] * Running_Sales)/(Receipts+Running_Sales) AS MONEY) AS [Weighted True Cost] FROM CTE 
WHERE RNK = RNK - 1 
)
SELECT * FROM CTE
ORDER BY [TRANS DATE] asc

Приведенный выше код теоретически мне нужен, но я наверняка использую терминатор неправильно, поскольку он точно так же выплевываетРасчет как якорь рекурсивного CTE.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Вы можете использовать для этого рекурсивный cte, например:

WITH cte AS (
    -- numbering is required for rcte
    SELECT *, ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY TRANS_DATE) AS rn
    FROM TrueMarginCalc
), rcte AS (
    -- base row for each partition
    SELECT *, CAST(TRUE_COST * RUNNING_SALES / TRUE_COST AS DECIMAL(18, 8)) AS WTC
    FROM cte AS base
    WHERE rn = 1
    UNION ALL
    -- next row for each partition
    SELECT curr.*, CAST(prev.WTC * curr.RUNNING_SALES / curr.TRUE_COST AS DECIMAL(18, 8))
    FROM cte AS curr
    INNER JOIN rcte AS prev ON curr.WHS = prev.WHS AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte

К сожалению, формула неполна, но приведенный выше запрос показывает, как получить доступ к столбцам из текущей строки и предыдущей итерации.

0 голосов
/ 19 декабря 2018

Я не на 100% по поводу формулы, но вы можете попробовать это.

SELECT WHS, PRODUCT, [TRANS DATE], RECEIPTS, [TRUE COST], [RUNNING_SALES]
    , (
        CASE [TRUE COST]
            WHEN 0.0 THEN LAG([True Cost]) OVER(PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE])
            ELSE (COALESCE( LAG([True Cost]) OVER(PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]), [TRUE COST] ) + [True Cost]) / 2
        END
    ) AS [WeightedTrueCost]
FROM dbo.TrueMarginCalc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...