MySQL 5 到 8 查询迁移(重写) - 表达式中的变量

MySQL 5 to 8 query migration (rewrite) - variables within expressions

提问人:Jimmix 提问时间:3/23/2019 最后编辑:informatik01Jimmix 更新时间:1/23/2021 访问量:1148

问:

我有一个 MySQL 5 查询,它生成了所需的输出,但在 MySQL 8 上带有警告。

我对变量的查询:

DROP TABLE IF EXISTS test;

CREATE TABLE test
( 
 id SERIAL PRIMARY KEY
 , percent DECIMAL(5,2) NOT NULL
);

INSERT INTO test (percent) VALUES 
(-0.50)
,(0.50)
,(1.00)
,(-0.20)
,(0.50)
,(-1.0)
,(-2.0)
,(0.75)
,(1.0)
,(0.50)
;

SELECT 
    percent,

    CASE @i 
        WHEN 0 THEN ROUND(@i:=(@i+(percent * 1)),2) -1
        ELSE ROUND(@i:=(@i+(percent * ABS(@i))) ,2) -1
    END total_percent

FROM 
    test
    , (SELECT @i:=1) vars         
ORDER 
    BY id; 

此问题
的答案之一,并产生所需的输出:

+---------+---------------+
| percent | total_percent |
+---------+---------------+
|   -0.50 |         -0.50 |
|    0.50 |         -0.25 |
|    1.00 |          0.50 |
|   -0.20 |          0.20 |
|    0.50 |          0.80 |
|   -1.00 |         -1.00 |
|   -2.00 |         -3.00 |
|    0.75 |         -1.50 |
|    1.00 |         -1.00 |
|    0.50 |         -0.50 |
+---------+---------------+
10 rows in set, 3 warnings (0.00 sec)

但有 3 个警告:

警告 |1287 |在表达式中设置用户变量是 已弃用,并将在将来的版本中删除。考虑 alternatives: 'SET variable=expression, ...', 或 'SELECT expression(s) INTO 变量'。

如何使用:

替代项: 'SET variable=expression, ...' 或 'SELECT expression(s) INTO 变量'。

并更改此查询,使其不会在 MySQL 8 上生成警告?

是否有任何关于如何正确重写从 MySQL5 到 MySQL8 的查询的一般指南或建议/示例集,以便在 MySQL8 上没有警告?

我希望一般来说,从 MySQL 5 到 MySQL 8 的变量不是唯一需要重写的变量,那还有什么呢?


请注意,问题不在于使用 CTE,而在于将变量的用法从 MySQL 5 重写到 MySQL 8 查询,而不会产生任何警告或错误。

此外,这个问题只是关于在数据库服务器上产生预期的结果,只需一个查询(如果可能的话)

MySQL 变量 迁移 警告

评论

1赞 Bill Karwin 3/24/2019
您提出的上一个问题中提供了一个解决方案,使用递归 CTE 查询。除此之外,如果你想要一个没有递归的迭代解决方案,你应该只从数据库中获取未计算的值,并在你的应用程序代码中以迭代方式进行计算。
0赞 Jimmix 3/24/2019
@BillKarwin这个问题不是重复的,因为它特别要求一种不使用 CTE 的申请方式,+ 如何 - 什么是不兼容?带有 ans. 的链接问题仅用于用作示例的特定 sql 查询的背景。获取原始数据并在数据库外部计算并将其插入回去,这与使用数据库本身进行大规模数据处理的整个意义背道而驰,但当数据集较小时(不是我的情况),这是一个选择alternatives: 'SET variable=expression, ...', or 'SELECT expression(s) INTO variables(s)'.rewrite properly a query from MySQL5 to MySQL8
1赞 Bill Karwin 3/24/2019
我将推翻接近的投票,但替代方案是:(1) 使用如图所示的 CTE,或 (2) 将所有结果提取到您的应用程序中,并使用代码而不是 SQL 逐步计算值。
0赞 Paul Spiegel 3/28/2019
SET ..或者不会帮助你解决这个任务。您要么需要迭代,要么需要乘法聚合函数。两者在 SQL 中都不可用。但是迭代可以用递归代替。因此,您的另一个问题已经给出了答案。而且您仍然忽略了另一个问题的评论。您没有 PK,也没有订单列。所以实际上没有可能的答案。SELECT .. INTO
0赞 Jimmix 3/28/2019
@Paul Spiegel:如果测试表已经改变,所以它有PK和列的顺序,答案可能吗?

答:

-1赞 Bill Karwin 4/2/2019 #1

替代方案是:

  1. 使用 CTE,如上一个问题的答案中所示。
  2. 将所有结果提取到应用程序中,并使用代码(而不是 SQL)逐步计算值。

评论

4赞 5/6/2019
我来寻找同一问题的答案。你和 OP 可能会在被问到的上下文中理解这个答案,但在事件发生后我不知道 CTE 是什么,我现在必须去寻找 OP 之前的问题,看看它是否有帮助。可悲的是,这个“答案”并不是特别有用。
0赞 Bill Karwin 5/6/2019
@ReddHerring 所以你认为因为你不理解正确答案而投反对票是合适的?
4赞 5/6/2019
不 - 我认为对答案投反对票是合适的,因为它不是答案