通过不重复计算优化sql查询

通过不重复计算优化sql查询,sql,oracle,math,case,Sql,Oracle,Math,Case,以下是我试图从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 .... 我怎样才能不重复上面的总和呢 如果大于0,“结果”应包含上述表达式

以下是我试图从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 ....
我怎样才能不重复上面的总和呢

如果大于0,“结果”应包含上述表达式的-value

                    -  0 if the value of expression is <= 0.
-0如果表达式的值为则使用派生表:

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 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

假设出于性能原因,您希望取消数学运算,那么(从DBA的角度来看)最好的方法是创建另一个名为
result
的列,然后使用insert/update触发器在行更改时自动填充该列,并使用您想要的值:

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仍然无法区分NULL和空字符串,所以谁知道呢?:-)

假设出于性能原因,您希望取消数学运算,最好的方法(从DBA的角度来看)是创建另一个名为
result
的列,然后使用insert/update触发器在行更改时自动填充该列,并使用您想要的值:

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仍然无法区分NULL和空字符串,所以谁知道呢?:-)

在这种情况下,您可以将case表达式替换为:

GREATEST( nvl(num1,0) + nvl(num2,0) - nvl(num3,0), 0 )

不过,OrbMan的答案通常更有用。

在这种情况下,您可以将您的case表达式替换为:

GREATEST( nvl(num1,0) + nvl(num2,0) - nvl(num3,0), 0 )

不过,OrbMan的答案通常更有用。

您确定这确实导致了查询中的问题吗?将THEN改为1,而不是求和,然后看看它是否真的产生了差异。否则,您将徒劳无功地完成所有这些工作。您确定这确实会导致查询中出现问题吗?将THEN改为1,而不是求和,然后看看它是否真的产生了差异。否则,您将徒劳无功,为什么不进行子查询:
select nvl(num1,0)+nvl(num2,0)+nvl(num3,0)sumof3nums,name from MyTable
?嗯,为什么顶级查询需要
nvl
?实际上可能是null还是
sumall
为null?@Frus:因为没有
ELSE
子句,当第一个大小写不匹配时,case语句将返回
null
。可以使用
ELSE
子句编写,结果相同。为什么不进行子查询:
select nvl(num1,0)+nvl(num2,0)+nvl(num3,0)sumof3nums,name from MyTable
?嗯,为什么顶级查询需要
nvl
?实际上可能是null还是
sumall
为null?@Frus:因为没有
ELSE
子句,当第一个大小写不匹配时,case语句将返回
null
。它可以用
ELSE
子句编写,结果相同。