2010-05-05 74 views
1

這裏優化SQL查詢在Oracle中查詢我試圖從去除多餘的數學運算:通過不重複數學

SELECT名字,

 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

    - 0 if the value of expression is <= 0. 
+2

你確定這實際上是在查詢中造成問題嗎?將THEN更改爲1而不是總和,並查看它是否確實有所作爲。否則,你將通過所有這些努力沒有任何好處 – CaffGeek 2010-05-05 18:43:56

回答

3

使用派生表:

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

爲什麼不創建子查詢:'select nvl(num1,0)+ nvl(num2,0)+ nvl(num3,0)sumof3nums,從MyTable'命名? – FrustratedWithFormsDesigner 2010-05-05 18:46:52

+1

@Frus:是的,正在這樣做.. – RedFilter 2010-05-05 18:47:53

+0

嗯,爲什麼頂級查詢需要'nvl'?它是否可行或可能是否爲空? – FrustratedWithFormsDesigner 2010-05-05 18:58:58

3

假設你想擺脫數學的性能方面的原因,從數據庫管理員的角度來看,這樣做的最好方法是創建另一個名爲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咕嚕聲便宜(比較關於數據庫性能的數據庫問題數量與存儲要求數據庫問題的數量 - 前者大大超過後者)。
  • 隨着表格變大,具有每行功能的數據庫查詢很難很好地擴展。

這都是假設甲骨文有觸發器當然是。我自己是一個DB2的人,但如果甲骨文腦死了,沒有他們,我會感到驚訝。然後再次,對於我所知道的,也許Oracle 仍然無法區分NULL和一個空字符串,那麼誰知道呢? :-)

4

在這種情況下,你可以將其替換您的CASE表達式:

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

OrbMan的回答是更普遍有用的,。