【发布时间】:2021-01-15 00:14:04
【问题描述】:
我有一个由查询生成器生成的查询,它依赖于查询中用户变量的计算来影响查询中其他输出的生成。作为查询的一个简单示例,它可能看起来像这样:
SELECT * FROM (
SELECT a, b, c,
@d := a * b AS d,
@e := (SELECT MAX(x) FROM t2 WHERE x > @d) AS e,
@f := @e * c AS f,
...
FROM t1
WHERE <column-filtering>
) tt
WHERE <variable-filtering>
这个系统的数据库服务器最近升级到了 MySQL8,这个查询现在产生了很多 1287 警告:
在表达式中设置用户变量已被弃用,并将在未来的版本中删除。考虑替代方案:“SET variable=expression, ...”或“SELECT expression(s) INTO variables(s)”。
客户不满意。
查询是以这种方式构建的(而不是将其实现为多个查询),以允许根据计算值和表列过滤结果。由于所涉及的表可能非常大,但过滤后的结果要小得多,因此需要在数据库服务器上过滤结果,以避免将大型结果集传输到计算服务器并在那里过滤的开销(和成本)。
我创建了一个small fiddle 作为包含真实数据的实际查询的精简版本(有 14 个变量,有些变量多达 ~100 个)。如何重构此查询以删除变量?
【问题讨论】:
-
你试过
SELECT 2 into @a而不是@a:=2吗? -
您不能在一个查询中执行多个查询,结果取决于先前的计算。此外,您只能将
SELECT ... INTO与 1 行数据一起使用 -
如果您打算尽可能少地使用这些内部表达式进行更改,您可以按照警告的建议进行操作并使用
SET语句——在游标循环中。否则,您可能会首先挑选出那些真正依赖于其他变量的表达式的最小部分,然后将这些计算提取到外部SELECT。 -
这个查询无论如何都被破坏了。它在不同的表达式中分配和使用变量——甚至早期版本的 MySQL 也警告过。
-
@GordonLinoff 同意,但它一直在工作。我对你关于如何重构它的建议感兴趣。