通过不重复数学来优化 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 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL去重复查询

sql语句去重

SQL

优化 SQL 查询以避免重复

如何将两个List合并,且其中不允许出现重复的项

SQL 优化器/执行计划 - 重复子查询