2017-06-07 46 views
2

我有一個存儲過程,它會返回一些行,並返回SELECT。在SELECT內,我需要檢查一個條件以便爲某些列返回正確的值。這個條件由一個標量函數組成。所有時間標量函數被調用,正在處理的行相同的參數,見下圖:SQL Server(T-SQL):多次避免調用標量函數

SELECT 
    Id, 
    Name, 
    Surname, 
    CASE WHEN (dbo.GetNumTravels(Id) >= 50) 
     THEN 10 
     ELSE 99 
    END as Factor1, 
    CASE WHEN (dbo.GetNumTravels(Id) >= 50) 
     THEN 15 
     ELSE -1 
    END as Factor2, 
    CASE WHEN (dbo.GetNumTravels(Id) >= 50) 
     THEN 30 
     ELSE 70 
    END as Factor3 
FROM 
    Employees 
WHERE 
    DepartmentId = 100 

我擔心的表現,我的意思是,我不喜歡把標量函數dbo.GetNumTravels倍數倍,因此如何避免這種情況,只調用一次,然後使用它所有的時間,我需要它?

+0

爲什麼你首先要求這個? 「GetNumTravels」做什麼,爲什麼它慢?如果你想查找每個員工的旅行,你應該在WHERE子句中使用連接或子查詢,而不是SELECT子句中的單個查詢。您可以使用* view *而不是函數,並使用'Employees'將其加入 –

回答

1

您可以通過使用派生表的概念實現這一目標,在派生表我們曾經打電話功能dbo.GetNumTravels(Id)只有一次,在外部查詢中使用它的輸出,這可能有助於在通過避免同樣的功能多次調用一定程度上獲得性能。

SELECT 
     Id, 
     Name, 
     Surname, 
     CASE WHEN (NumTravelsID >= 50) THEN 10 ELSE 99 END as Factor1, 
     CASE WHEN (NumTravelsID >= 50) THEN 15 ELSE -1 END as Factor2, 
     CASE WHEN (NumTravelsID >= 50) THEN 30 ELSE 70 END as Factor3 
FROM (
     SELECT 
      Id, 
      Name, 
      Surname, 
      dbo.GetNumTravels(Id) as NumTravelsID 
     FROM Employees 
     WHERE DepartmentId = 100 
)M 
2

標量用戶定義函數對於糟糕的性能而言是臭名昭着的。如果您可以將其轉換爲內聯表值函數,您可以期望看到性能提升。

如果您將您的標量函數內嵌表值函數可以調用它一次使用cross apply()像這樣的每一行:

select 
    Id, 
    Name, 
    Surname, 
    case when x.NumTravels >= 50 
     then 10 
     else 99 
    end as Factor1, 
    case when x.NumTravels >= 50) 
     then 15 
     else -1 
    end as Factor2, 
    case when x.NumTravels >= 50 
     then 30 
     else 70 
    end as Factor3 
from Employees 
    cross apply dbo.GetNumTravels_itvf(e.Id) x 
where DepartmentId = 100 

參考:

0

我不知道表演(反正,做你的測試考慮其他的答案也是如此),但我想對此進行測試。我試圖減少功能的使用和CASE的使用。請讓我知道

SELECT A.* 
    , 10*F0+99*~F0 AS FACTOR1 
    , 15*F0-1*~F0 AS FACTOR2 
    , 30*F0+70*~F0 AS FACTOR3 
FROM (
    SELECT 
    Id, 
    Name, 
    Surname, 
    CAST(CASE WHEN (dbo.GetNumTravels(Id) >= 50) THEN 1 ELSE 0 END AS BIT) AS F0  
    FROM Employees 
    WHERE DepartmentId = 100 
    ) A