MySQL 8 - пользовательские переменные в выражениях устарели (сложный расчет)

// РЕДАКТИРОВАТЬ //

Ниже приведен исходный вопрос, но моя проблема действительно может быть упрощена одним вопросом... как я могу получить приведенный ниже вывод без использования пользовательских переменных?!

SELECT ID, @cumu_return:=IF(id = 1, 1, @cumu_return + (@cumu_return * ret)) AS cumulative_return 
FROM (
    SELECT 1 AS ID, 1 AS num, 0.1 AS ret UNION ALL
    SELECT 2 AS ID, 1 AS num, 0.1 AS ret UNION ALL
    SELECT 3 AS ID, 1 AS num, 0.1 AS ret UNION ALL
    SELECT 4 AS ID, 1 AS num, 0.1 AS ret UNION ALL
    SELECT 5 AS ID, 1 AS num, 0.1 AS ret
) t

// КОНЕЦ РЕДАКТИРОВАНИЯ //

У меня есть таблица следующим образом...

CREATE TABLE `daily_return` (
  `id` int(11) NOT NULL,
  `list_id` int(11) NOT NULL,
  `last_updated` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
  `daily_return` float NOT NULL,
  `last_return` float NOT NULL, KEY (`id`)
)

"ежедневный доход" - это процентное изменение цены для list_id, рассчитываемое каждый день, а last_return - первый / начальный номер возврата.

Мне нужно рассчитать совокупный показатель возврата, используя следующую логику:

'Previous Day Return' + ('Previous Day Return' * 'Daily Return')

Следовательно, у меня есть следующий запрос...

INSERT INTO cmc_cumulative_return (list_id, last_updated, cumulative_return)
SELECT list_id, last_updated, cumulative_return FROM (
    SELECT id, list_id, last_updated, daily_return, last_return,
        @cumu_return:=IF(id = 1, last_return, @cumu_return + (@cumu_return * daily_return)) AS cumulative_return 
    FROM daily_return c
) t WHERE id <> 1;

Когда я запускаю это внутри процедуры, выдается предупреждение:

Установка пользовательских переменных в выражениях устарела и будет удалена в следующем выпуске. Пожалуйста, установите переменные в отдельных выражениях.

Я видел некоторые другие подобные вопросы о stackru, но все они были простыми вычислениями приращений, которые можно заменить на ROW_NUMBER() OVER или SUM() OVER, но я не могу понять, как удалить переменные в моем запросе выше.

Первоначально я использовал 3-4 переменные, но теперь я сократил их до одной и запросил вашу помощь, удалив последнюю.

РЕДАКТИРОВАТЬ 2

Запрос с фактическими данными: (расчет Гордона включен)

SELECT id, list_id, last_updated, daily_return, last_return,
    @cumu_return:=IF(id = 1, last_return, @cumu_return + (@cumu_return * daily_return)) AS cumulative_return,
    (
        EXP(SUM(LN(1 + daily_return)) OVER (ORDER BY id)) / (1 + daily_return)
    ) as cumulative_return2
FROM (
    SELECT 1 AS id, 2 AS list_id, '2019-02-20' AS last_updated, 0 AS daily_return, 1.15 AS last_return UNION ALL
    SELECT 2 AS id, 2 AS list_id, '2019-02-21' AS last_updated, 0.0145999858 AS daily_return, 1.15 AS last_return UNION ALL
    SELECT 3 AS id, 2 AS list_id, '2019-02-22' AS last_updated, -0.0503679203 AS daily_return, 1.15 AS last_return UNION ALL
    SELECT 4 AS id, 2 AS list_id, '2019-02-23' AS last_updated, 0.0111594238 AS daily_return, 1.15 AS last_return
) t

1 ответ

Решение

Вы можете использовать натуральные бревна и возведение в степень для расчета совокупного продукта.

INSERT INTO cmc_cumulative_return (list_id, last_updated, cumulative_return)
    SELECT list_id, last_updated, 
           (MAX(CASE WHEN id = 1 THEN last_return END) OVER () *
            EXP(SUM(LN(1 + daily_return)) OVER (ORDER BY id)
               ) / (1 + daily_return)
           ) as cumulative_return
    FROM daily_return c;

Если вы действительно хотите исключить, где id = 1, то это требует дополнительного уровня подзапросов.

Вот дб<> скрипка.

Другие вопросы по тегам