通过不重复数学来优化 sql 查询
Posted
技术标签:
【中文标题】通过不重复数学来优化 sql 查询【英文标题】:optimizing the sql query by not repeating the math 【发布时间】:2010-05-05 18:41:18 【问题描述】:这是我试图从中删除冗余数学运算的 Oracle 查询:
选择名称,
CASE
when nvl(num1,0) + nvl(num2,0) - nvl(num3,0) > 0
THEN nvl(num1,0) + nvl(num2,0) - nvl(num3,0)
ELSE 0
END
as result,
.... from ....
上面的总结怎么不重复?
“结果”应包含 - 上述表达式的值 if > 0
- 0 if the value of expression is <= 0.
【问题讨论】:
您确定这实际上是导致查询出现问题的原因吗?将 THEN 更改为 1 而不是总和,看看它是否真的有所作为。否则,您将白费力气地进行所有这些努力 【参考方案1】:在这种情况下,您可以将 CASE 表达式替换为:
GREATEST( nvl(num1,0) + nvl(num2,0) - nvl(num3,0), 0 )
OrbMan 的回答通常更有用。
【讨论】:
【参考方案2】:使用派生表:
select name, nvl(CASE when sumall > 0 THEN sumall end, 0) as result
from (
select nvl(num1,0) + nvl(num2,0) - nvl(num3,0) sumall, name
from MyTable
) a
【讨论】:
为什么不做子查询:select nvl(num1, 0)+nvl(num2, 0) + nvl(num3, 0) sumof3nums, name from MyTable
?
嗯,为什么***查询中需要nvl
?是否有可能为 null 或 sumall
?
@Frus: 因为没有ELSE
子句,当第一个case 不匹配时,case 语句将返回NULL
。它可以用ELSE
子句代替,结果相同。【参考方案3】:
假设您出于性能原因想要摆脱数学,最好的方法(从 DBA 的角度来看)是创建另一个名为 result
的列,然后使用插入/更新触发器自动填充当一行发生变化时,使用你想要的值:
CASE
WHEN nvl(num1,0) + nvl(num2,0) - nvl(num3,0) > 0
THEN nvl(num1,0) + nvl(num2,0) - nvl(num3,0)
ELSE 0
END
这样,计算仅在需要时进行(在行创建/更改时),而不是每次读取。这分摊了读取次数多于写入次数的数据库的操作成本(根据我的经验,这与所有数据库都接近)。
那么你的查询就变得简单而快速:
select name, result from ...
此方法有效,因为:
绝大多数数据库确实阅读频率远高于写入频率;和 磁盘空间比 CPU grunt 便宜(比较有关数据库性能的数据库问题与有关存储要求的问题 - 前者大大超过后者)。 具有每行函数的数据库查询很少随着表变大而很好地扩展。当然,这一切都假设 Oracle 具有 触发器。我自己是一个 DB2 人,但如果 Oracle 如此脑残以至于没有它们,我会感到惊讶。再说一次,据我所知,也许 Oracle 仍然 无法区分 NULL 和空字符串,所以谁知道呢? :-)
【讨论】:
以上是关于通过不重复数学来优化 sql 查询的主要内容,如果未能解决你的问题,请参考以下文章