说我有这样的查询:
select ((amount1 - amount2)/ amount1) as chg from t1
where
((amount1 - amount2)/ amount1) > 1 OR
((amount1 - amount2)/ amount1) < 0.3
有没有办法我只能执行一次算术运算,而不是像上面的查询那样进行三次?
编辑:我不确定数据库是否会自动优化查询以仅执行此类计算一次?我在Sybase上使用T-SQL。
答案 0 :(得分:10)
从概念上讲,您可以从计算中选择,即:
select
calc.amt
from
(select (amt1 - amt2) / amt1 as amt from #tmp) calc
where
calc.amt > 1 OR calc.amt < 0.3
如果SQL无论如何都会将你的代码优化为类似代码,那么不确定是不是最重要的 - 从基本临时表中查询我的查询似乎表明它们以相同的方式执行。
答案 1 :(得分:2)
重复算术运算比使用更多IO
更好- 稍后添加
我已经检查了SQL Server 2000,2005和2008中的所有3个解决方案(超过100,000个随机行),并且在所有情况下,它们具有完全相同的执行计划以及CPU和IO使用。
优化工具做得很好。
select calc.amtpercent
from ( select (amount1-amount2)/cast(amount1 as float) as amtpercent from z8Test) calc
where calc.amtpercent > 1 OR calc.amtpercent < 0.3
select (amount1-amount2)/cast(amount1 as float) as amtpercent
from z8Test
where (amount1-amount2)/cast(amount1 as float) > 1
or (amount1-amount2)/cast(amount1 as float) < 0.3
select (amount1-amount2)/cast(amount1 as float) as amtpercent
from z8Test
where (amount1-amount2)/cast(amount1 as float) not between 0.3 and 1
回答Alex评论:您曾经使用过数据库吗?我已经看过很多次IO的瓶颈而且从来没有在数据库服务器的CPU中。更确切地说,在我有很高CPU使用率的情况下,它是由IO瓶颈导致的,并且仅在两种情况下由于查询错误地使用了加密技术(而不是加密参数值并与巨大的表查询中的列进行比较是解密列并且在第二种情况下,对第一种情况和可疑数量的不必要的转换(日期时间到字符串和返回日期时间)进行比较,以查找非常频繁触发的查询。
当然你必须避免不必要的算术,但是如果你必须增加IO作为权衡,要小心。
答案 2 :(得分:1)
SQL不是一种命令式语言,它是一种声明性语言。您不应该使用C样式优化思维框架来处理SQL。例如,在您的查询中,与您的查询不是SARGable的事实相比,重复计算 if 它发生时是相关的。如果这种搜索与您的应用程序性能相关,那么RDBMS更适合在表级别创建表达式为((ammount1-ammount2)/ammount1)
的计算列并索引该列,然后重写您的查询以使用计算列:
ALTER TABLE t1 ADD chg AS ((ammount1-ammount2)/ammount1);
CREATE INDEX idx_t1_chg ON t1(chg);
GO
SELECT chg FROM t1 WHERE chg > 1 OR chg < 0.3;
GO
答案 3 :(得分:-2)
我认为这应该有效:
select ((amount1 - amount2)/ amount1) as chg from t1
where
chg > 1 OR
chg < 0.3
编辑:经过一次小测试后我发现这不起作用:列名'chg'无效。克里斯的回答是一个更好的解决方案。