2013-11-20 39 views
3

我正在使用SQL 2k5 sproc。在Sproc中多次使用UDF

我需要引用UDF來根據幾個變量和用戶權限計算價格。我最初試圖這一點,但它沒有工作,因爲我沒有引用一個場...

SELECT dbo.f_GetPrice(model,userid,authType) 'YourPrice', name, description 
FROM tblRL_Products 
WHERE 'YourPrice' Between @fromPrice AND @toPrice 
    OR 'YourPrice' IS NULL 

所以我修改這

SELECT dbo.f_GetPrice(model,userid,authType) 'YourPrice', name, description 
FROM tblRL_Products 
WHERE dbo.f_GetPrice(model,userid,authType) Between @fromPrice AND @toPrice 
    OR dbo.f_GetPrice(model,userid,authType) IS NULL 

當SQL執行該存儲過程,它是運行函數3X的每個記錄或它是否運行一次,並使用其他兩個位置每行的值。

有沒有更有效的方法來做到這一點?


編輯

這是標量UDF。它需要根據用戶授權的類型獲取價格,然後一旦我們有合適的價格,我們需要對其進行計算。這全部存儲在授權表中。每個用戶都有對每一行產品的授權。因此,他們可能會針對每條線有不同的價格類型和計算方式,在單個搜索結果調用中返回數十行甚至數百行。

在上面的代碼中,我使用了authType,這是一箇舊的調用,我們不再使用該參數。

ALTER function [dbo].[f_GetPrice] 
(
    @model uniqueidentifier, 
    @userID uniqueidentifier  
) 
returns money 
as 
begin 

Declare @yourPrice money 

WITH ProductPrice AS(
SELECT (CASE PriceType 
     WHEN 'msrp' THEN p.price_msrp 
      WHEN 'jobber' THEN p.price_jobber 
      WHEN 'warehouse' THEN p.price_warehouse 
      WHEN 'margin' THEN p.price_margin 
      WHEN 'mycost' THEN p.price_mycost 
      WHEN 'customprice1' THEN p.price_custom1 
      WHEN 'customprice2' THEN p.price_custom2 
      WHEN 'customprice3' THEN p.price_custom2 
      ELSE p.price_msrp 
     END) as YourPrice, aup.calc, aup.amount 
FROM products p 
    JOIN lines l ON l.lineID=l.lineID 
    JOIN authorizations a ON l.authlineID=a.authlineID 
    JOIN authorizationusers au ON a.auID=au.auID 
    JOIN authorizationuserprices aup ON au.aupID=aup.aupID 
WHERE [email protected] AND [email protected]) 


SELECT @yourPrice=(CASE calc 
      WHEN 'amount' THEN YourPrice+amount 
      WHEN 'percent' THEN YourPrice+(YourPrice*amount/100) 
      WHEN 'divide' THEN YourPrice/amount 
      WHEN 'factore' THEN YourPrice*amount 
      WHEN 'none' THEN YourPrice 
      ELSE YourPrice 
      END) FROM ProductPrice 

return @yourPrice 

END 
+3

更好的,請出示dbo.f_GetPrice'的'代碼,我們可以幫你把它*** ***真的很好 – swasheck

回答

5

如果你必須使用這個UDF,那麼使用子查詢和過濾的子查詢外:

select YourPrice, name, description 
from 
(
    SELECT dbo.f_GetPrice(model,userid,authType) YourPrice, name, description 
    FROM tblRL_Products 
) d 
WHERE YourPrice Between @fromPrice AND @toPrice 
    OR YourPrice IS NULL 

然後你只叫你的UDF一次,而不是3倍。

+0

我簡化了一個複雜的sproc以顯示問題,而不需要額外的東西。我已經在子查詢中使用它來進行分頁。我想過這樣做,但是我擔心的是,當我只是真的回來時,我會在很多情況下帶回一堆記錄。因此,我會抓住所有符合其他批評的記錄,以便稍後將其刪除到我在子查詢之外需要的打印。這似乎需要比過濾前更長的時間。這就是爲什麼我沒有那樣做。 –

0

如果標量函數必須應用於相當多的行,則標量函數並不好。在這種情況下,您肯定可以將標量函數轉換爲表值函數,對於每一行輸入數據都不會被調用一次。

create function [dbo].[ft_GetPrice] 
(
    @model uniqueidentifier, 
    @userID uniqueidentifier  
) 
returns table 
as return 
(
    WITH ProductPrice AS (
     SELECT (CASE PriceType 
       WHEN 'msrp' THEN p.price_msrp 
        WHEN 'jobber' THEN p.price_jobber 
        WHEN 'warehouse' THEN p.price_warehouse 
        WHEN 'margin' THEN p.price_margin 
        WHEN 'mycost' THEN p.price_mycost 
        WHEN 'customprice1' THEN p.price_custom1 
        WHEN 'customprice2' THEN p.price_custom2 
        WHEN 'customprice3' THEN p.price_custom2 
        ELSE p.price_msrp 
       END) as YourPrice, aup.calc, aup.amount 
     FROM products p 
      JOIN lines l ON l.lineID=l.lineID 
      JOIN authorizations a ON l.authlineID=a.authlineID 
      JOIN authorizationusers au ON a.auID=au.auID 
      JOIN authorizationuserprices aup ON au.aupID=aup.aupID 
     WHERE [email protected] AND [email protected] 
    ) 
    SELECT 
     CASE calc 
      WHEN 'amount' THEN YourPrice+amount 
      WHEN 'percent' THEN YourPrice+(YourPrice*amount/100) 
      WHEN 'divide' THEN YourPrice/amount 
      WHEN 'factore' THEN YourPrice*amount 
      WHEN 'none' THEN YourPrice 
      ELSE YourPrice 
     END as YourPrice 
    FROM ProductPrice 
) 
GO 

哪些可以再使用:

SELECT fp.YourPrice, name, description 
FROM tblRL_Products 
    outer apply dbo.ft_GetPrice(model, userid, authType) fp 
WHERE fp.YourPrice Between @fromPrice AND @toPrice OR fp.YourPrice IS NULL 
+0

我現在要測試這個。所以創建表值函數比標量更快。它仍然必須爲每一行運行。這是什麼讓標量在大型返回集上變得更糟,而不是表中的值呢?當他們對每一行都做幾乎相同的事情時?肯定地嘗試這個,但只是好奇我對標量UDF有明顯的誤解。 –

+0

@IshmaelStruan,是的,表函數也在爲每一行輸入數據進行計算,但與標量函數內聯表值函數相比,它將一次對所有輸入行執行集合操作。就像如果你會執行一個查詢'select ...來自tblRL_Products加入產品p ...加入授權用戶等等。在標量函數的情況下,應該發生調用,然後應該計算結果,然後還應該發生從調用返回的情況。即使是1msec的微小開銷,可能導致10秒鐘的調用/返回。在相對較小的10k行集上開銷。 –