2017-06-07 44 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