如何避免反复调用sum()的CPU密集型函数



我有一个函数,它对传递的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

最新更新