我有一个函数,它对传递的id执行cpu繁重的计算我正在编写一个报告来总结结果,但出于性能原因,我只想对每个id
调用该函数一次。下面是一个简单的SQL示例,但是它为每个列调用函数一次。我如何重写查询,只调用函数一次每个标识符?
SELECT
SUM( case myfunction(employee_id) WHEN 'bob' THEN 1 ELSE 0 END) as "bob total",
SUM( case myfunction(employee_id) WHEN 'joe' THEN 1 ELSE 0 END) as "Joe total",
SUM( case myfunction(employee_id) WHEN 'tom' THEN 1 ELSE 0 END) as "Toms total"
FROM employee
您可以在进行求和之前将逻辑放入子查询中,然后引用单列。
SELECT
SUM( case FunctionResult WHEN 'bob' THEN 1 ELSE 0 END) as "bob total",
SUM( case FunctionResult WHEN 'joe' THEN 1 ELSE 0 END) as "Joe total",
SUM( case FunctionResult WHEN 'tom' THEN 1 ELSE 0 END) as "Toms total"
FROM
( SELECT myfunction(employee_id) AS FunctionResult
FROM employee
) AS e;
在性能方面,一个更好的解决方案是看看你的标量函数实际上是做什么的,然后问你自己它是否需要是一个函数,你能让解集是基于的吗?
代替FROM employee
,使用如下定义的派生表:
SELECT *, myfunction(employee_id) AS myFuncResult
FROM employee
现在,您有myFuncResult
作为附加列。希望优化器不会打乱这个策略。它没有很好地理解标量函数的代价(事实上,没有)。
由于您正在使用SQL Server,您可以尝试CROSS APPLY表达式,只需将.Result替换为您的函数返回的列的名称:
SELECT
SUM( case func.Result WHEN 'bob' THEN 1 ELSE 0 END) as "bob total",
SUM( case func.Result WHEN 'joe' THEN 1 ELSE 0 END) as "Joe total",
SUM( case func.Result WHEN 'tom' THEN 1 ELSE 0 END) as "Toms total"
FROM employee e
CROSS APPLY myfunction(e.employee_id) as func