【问题标题】:MySQL 8 - user variables within expressions is deprecated (complex calculation)MySQL 8 - 表达式中的用户变量已弃用(复杂计算)
【发布时间】:2019-02-23 18:01:18
【问题描述】:

// 编辑 //

以下是原始问题,但我的问题可以通过一个问题真正简化...如何在不使用用户变量的情况下获得以下输出?!

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;

当我在一个过程中运行它时,它会抛出一个警告:

不推荐在表达式中设置用户变量,并将 在未来的版本中删除。请单独设置变量 而是声明。

我在stackoverflow上看到了一些其他类似的问题,但它们都是简单的增量计算,可以用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

【问题讨论】:

  • @GordonLinoff 我添加了一个非常简单的备用查询。

标签: mysql sql deprecation-warning user-variables


【解决方案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 的地方,那么这需要额外的子查询级别。

Here 是一个 dbfiddle。

【讨论】:

  • 这种查询在 last_return 等于 '1' 时有效。我用一些实际数据对问题进行了第二次编辑。您能否调整公式以考虑last_return?基本上,last_return 是程序最后一次运行时的累计总数,并且程序会进一步计算新数据的累计总数。
  • @ShahidThaika 。 . .你试过 dbfiddle 吗?这应该与您的查询做同样的事情。
  • 我注意到我的查询中有一条评论。您能否尝试在 MySQL 中运行您在此小提琴中找到的查询。您会看到这两列给出不同的值。这是因为我的 daily_return 以“0”开头。 dbfiddle.uk/…
猜你喜欢
  • 1970-01-01
  • 2019-07-08
  • 2019-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多