2009-07-01 57 views
2

說我有這樣的查詢:我如何調整這個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

回答

2

最好是有反覆運算超過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作爲折衷。

-2

這應該工作,我認爲:

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

10

從概念上講,你可以從你的計算選擇,即:

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

不知道把我的頭頂部,如果SQL無論如何都會優化你的代碼以類似的 - 對我查詢過一個基本的臨時表運行查詢似乎表明他們以相同的方式執行。

1

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