我在stackoverflow中进行了搜索但是没有找到我问题的确切答案,所以请尽可能帮助我。
我想'建立一个这样的SQL语句:
SELECT
@tax1 := (complicated calculation formula),
@owe := (another complicated calculation formula),
IF(@owe=0, 0,@tax1/@owe)
FROM ...
但是,在MySQL关于user-defined variables的文档中,它建议反对它说:
作为一般规则,您不应该为用户变量赋值并在同一语句中读取值。您可能会得到您期望的结果,但这不能保证。涉及用户变量的表达式的评估顺序是未定义的,可能会根据给定语句中包含的元素进行更改;此外,MySQL服务器版本之间的订单不保证相同。在SELECT @ a,@ a:= @ a + 1,...中,你可能会认为MySQL会首先评估@a然后再进行一次赋值。但是,更改语句(例如,通过添加GROUP BY,HAVING或ORDER BY子句)可能会导致MySQL选择具有不同评估顺序的执行计划。
我的目标是避免复制和粘贴那些非常复杂的公式,因为它会妨碍可读性,如果公式发生变化,我需要确保它在所有地方都有变化 - 但我知道这样做,它'工作得很好。
此外,我知道ALIAS 不有效,因为别名只能在GROUP BY,HAVING和ORDER子句中使用。
我在其他一些帖子中读到先做一个子查询,首先计算@ tax1和@owe,然后使用另一个查询来组合结果。但我认为性能可能不如仅仅简单地复制和粘贴那些公式那样有效。
有没有人有任何建议他们会做什么?还是我坚持在可读性和性能之间做出选择?
提前致谢。
答案 0 :(得分:1)
是的,在没有用户变量的SQL中执行此操作的唯一方法是编写派生表子查询。然后,您可以使用列别名来引用这些复杂表达式的结果:
SELECT tax1, owe, IF(owe=0, 0,tax1/owe) AS ratio
FROM (
SELECT
(complicated calculation formula) AS tax1,
(another complicated calculation formula) AS owe
FROM ...
) AS _sub
MySQL在优化子查询方面存在一些问题,但派生表的情况不是坏的情况之一。
关于MySQL和子查询的警告是关于在WHERE子句中使用范围条件中的子查询。 MySQL无法弄清楚子查询是否是常量,并且它会重复地将子查询重新评估为依赖子查询,即使这不是必需的。
答案 1 :(得分:0)
我经常在select语句中使用变量进行顺序评估,聚合,组统计和数据分类。
这是一个例子:
MySQL列出每个类别的前X个记录,将每个记录与之前的差异相结合
create table if not exists
closemovers engine=memory
select
code
, date
, close
, rank
, prevclose
, sign
, cumm
from
( select
`code`
, `date`
, `close`
, @rank := if( @code = code , @rank + 1 , 1) as rank
, @prevclose := if( @code = code , cast( @prclose as decimal(10,3) ), null) as prevclose
, if(@code = code, sign( @prclose - close), NULL) as sign
, @cumm := if(@code = code and @psign = sign(@prclose - close), @cumm + 1 , 1) as cumm
, @psign := sign(@prclose - close)
, @code := code
, @prclose := close
from
companyhistory
order by
code, date
) as ranked
join
pricefeed
using (code)
where
rank < 10
and sign is not null ;
我希望这可以给你一个提示