2010-07-07 61 views
4

我有一個用戶定義的函數(例如myUDF(a,b)),它返回一個整數。由UDF產生的列的Where子句

我想,以確保此功能將只調用一次,其結果可以作爲WHERE子句中的條件:

SELECT col1, col2, col3, 
     myUDF(col1,col2) AS X 
From myTable 
WHERE x>0 

SQL Server試圖檢測x作爲列,但它是一個真正的計算值的別名。

如何重新編寫此查詢,以便可以對計算值進行過濾而不必多次執行UDF?

回答

5

,您可以使用跨應用:

Select T.col1, T.col2, FuncResult.X 
From Table As T 
    Cross Apply (Select myUdf(T.col1, T.col2) As X) As FuncResult 
Where FuncResult.X > 0 
+0

Cross Apply究竟是什麼? – Gzim 2010-07-08 08:47:38

+0

@Gzim - 思考交叉應用作爲派生表和相關子查詢之間的混合。實際上,它允許您加入引用查詢外部項目的子查詢。在我的示例中,我從From子句中的另一個表引用col1和col2。這裏是關於這個主題的另一篇文章:http://www.sqlteam.com/article/using-cross-apply-in-sql-server-2005 – Thomas 2010-07-08 13:35:28

+0

哦,這個男孩這是如此強大。尤其是當您在插入表格(同時)以及從表格UDF接受來自所選表格的參數時進行插入和選擇時出現複雜情況。 Thanx Thomas。 – Gzim 2010-07-20 09:04:49

4

嘗試

SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable 
WHERE dbo.myUDF(col1,col2) >0 

但要注意,這會導致掃描,因爲它不是SARGable

這裏是另一種方式

select * from(
SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable) as y 
WHERE x>0 
+0

是的,但這個功能是如此耗時,我試圖避免它使用兩次 – Gzim 2010-07-07 16:35:32

+0

那麼第一個案例應該只執行一次,第二個 - 公共表格表達方式(或Baaju的答案)絕對只應該計算一次 – Rup 2010-07-07 16:39:43

+0

僅僅因爲你兩次輸入函數並不意味着它會被調用兩次。 SQL Server可能會認識到它在兩個地方都是相同的功能,只能評估一次。 – Gabe 2010-07-07 16:43:30

2

SQL Server不允許你引用列別名。要麼你有兩次寫出列:

SELECT col1, col2, col3, myUDF(col1,col2) AS X 
From table myTable 
WHERE myUDF(col1,col2) > 0 

或者使用子查詢:如果您在使用SQL Server 2005及以後

SELECT * 
FROM (
     SELECT col1, col2, col3, myUDF(col1,col2) AS X 
     From table myTable 
     ) as subq 
WHERE x > 0 
0

我不是100%確定你在做什麼,但由於x不是列,我會從你的SQL語句中刪除它,所以你有:

SELECT col1, col2, col3, myUDF(col1,col2) AS X From myTable 

然後添加條件,你的代碼,所以你只能把它當x > 0

7
With Tbl AS 
(SELECT col1, col2, col3, myUDF(col1,col2) AS X 
     From table myTable ) 

SELECT * FROM Tbl WHERE X > 0 
+1

SQL Server 2005+的優秀答案! – 2010-07-07 16:39:39

1

根據UDF以及如何有用的或經常使用它,你可以考慮將它添加到表作爲computed column 。您可以按正常方式過濾列,而不必在查詢中寫出函數。

0

你的問題最好通過「With」子句(我認爲是MSSS中的CTE)來回答。

真的最好的問題是:我應該存儲此計算值還是爲每一行重新計算一次,每次查詢表時都要重新計算它。

表中有10行,總是10行?

是否不斷添加行?

您是否有清除策略或讓它增長?

每個月只查詢一次表格?

如果這是一個「長時間運行」的功能(即使你已經優化了它),爲什麼你要多次執行它?

您詢問過一次,但您確實需要每行查詢一次。

在索引或 「虛擬列」

優點存放答案:

計算每行一次。 查詢時間不會線性增長。

缺點: 增加插入/更新時間

計算每次

優點:

插入/更新時間優化

缺點: 查詢時間的增長與行數。 (不可擴展)

如果你每月查詢一次,爲什麼你關心性能有多糟糕,去調整一些實際上對你的操作有很大影響的東西(非常輕微的)。

如果你沒有在每秒插入一堆(取決於你的硬件)行數,那麼這段時間會花費多少時間來做出很大的改變?