我如何调整这个SQL执行算术计算一次

问题描述:

说我有这样的查询:我如何调整这个SQL执行算术计算一次

select ((amount1 - amount2)/ amount1) as chg from t1 
    where 
     ((amount1 - amount2)/ amount1) > 1 OR 
     ((amount1 - amount2)/ amount1) < 0.3 

有没有我可以执行算术计算只有一次,而不是三次做它的方式上面的查询?

编辑:我不确定数据库是否自动优化查询只做一次这样的计算?我在Sybase上使用T-SQL。

+3

你确定它不止一次地执行它吗? – 2009-07-01 09:06:31

最好是有反复运算超过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 

答:你有没有与数据库的工作?我见过很多次在IO中遇到瓶颈,从来没有在数据库服务器的CPU中遇到瓶颈。更确切地说,在少数情况下,当我的CPU使用率很高时,它是由IO瓶颈引起的,并且仅在两种情况下由于错误地使用了加密技术的查询(而不是加密参数值,并且在巨大表查询中与列进行比较是解密列和比较参数)和第二种情况下非常多的不必要的转换(日期时间到字符串并返回日期时间),这是对于真正频繁触发的查询。

当然,您必须避免不必要的算术,但要小心如果您必须增加IO作为折衷。

这应该工作,我认为:

select ((amount1 - amount2)/ amount1) as chg from t1 
where 
    chg > 1 OR 
    chg < 0.3 

编辑:小试后,我发现这不起作用:无效的列名“CHG”。克里斯的回答是更好的解决方案。

+0

如果没有,你可以将它包装在一个可以工作的子选择中。 – 2009-07-01 09:08:03

+0

至少在t-sql中这不起作用。 – Rahul 2009-07-01 09:09:20

从概念上讲,你可以从你的计算选择,即:

select 
    calc.amt 
from 
    (select (amt1 - amt2)/amt1 as amt from #tmp) calc 
where 
    calc.amt > 1 OR calc.amt < 0.3 

不知道把我的头顶部,如果SQL无论如何都会优化你的代码以类似的 - 对我查询过一个基本的临时表运行查询似乎表明他们以相同的方式执行。

SQL不是一种命令式语言,它是一种声明式语言。您不应该使用C风格优化思维框架来处理SQL。例如在您的查询重复计算,如果它发生,与您的查询不是SARGable事实相比是相关的。如果这种搜索与您的应用程序性能相关,那么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