我有一个存储过程,它会执行SELECT
以返回一些行。在SELECT
中,我需要检查一个条件,以便为某些列返回正确的值。这个条件包括标量函数。所有时间都会使用与正在处理的行相同的参数调用标量函数,请参见下文:
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
倍数,所以如何避免这种情况,只调用一次,然后一直使用它我需要它? / p>
答案 0 :(得分: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
参考:
答案 1 :(得分: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 :(得分: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