Tsql 当需要组合结果时,如何避免T-SQL函数被多次调用?

Tsql 当需要组合结果时,如何避免T-SQL函数被多次调用?,tsql,Tsql,我有两个T-SQL标量函数,它们都对大量数据执行计算(花费“很多”时间)并返回一个值,例如CalculateAllIncomes(EmployeeID)和CalculateAllExpenditures(EmployeeID) 我运行一个select语句,调用这些函数并为每个员工返回结果。我还需要每个员工的余额计算为AllIncomes AllExpenditures 我有一个函数GetBalance(EmployeeID),它调用上述两个函数并返回结果{CalculateAllIncomes(

我有两个T-SQL标量函数,它们都对大量数据执行计算(花费“很多”时间)并返回一个值,例如CalculateAllIncomes(EmployeeID)和CalculateAllExpenditures(EmployeeID)

我运行一个select语句,调用这些函数并为每个员工返回结果。我还需要每个员工的余额计算为AllIncomes AllExpenditures

我有一个函数GetBalance(EmployeeID),它调用上述两个函数并返回结果
{CalculateAllIncomes(EmployeeID)-CalculateAllExpenditures(EmployeeID)}
。但如果我这样做:

选择CalculateAllIncomes(EmployeeID)、CalculateAllExpenditures(EmployeeID)、GetBalance(EmployeeID)…
函数CalculateAllIncomes()和CalculateAllExpenditures会被调用两次(一次显式调用,一次在GetBalance函数内部调用),因此生成的查询所需时间是应该调用的两倍

我想找到更好的解决办法。我试过:

select alculateAllIncomes(EmployeeID), AS Incomes, CalculateAllExpenditures
(EmployeeID) AS Expenditures, (Incomes - Expenditures) AS Balance....
但它会抛出错误:

无效的列名和名称

列名无效

我相信一定有一个简单的解决办法,但我想不出来。出于某种原因,我似乎无法在SELECT子句中使用列别名。是这样吗?如果是这样的话,在这种情况下有什么解决办法?
谢谢您的建议。

忘记函数调用:您可能可以在一个普通查询中完成所有操作

函数调用被误用(试图进行OO封装)会迫使您陷入这种情况。此外,如果在Employee表中每行都有GetBalance(EmployeeID),则在该表上进行光标移动。而你现在也通过多次电话来解决这个问题

你需要的是这样的东西:

;WITH cSUMs AS
(
SELECT
    SUM(CASE WHEN type = 'Incomes' THEN SomeValue ELSE 0 END) AS Income),
    SUM(CASE WHEN type = 'Expenditures' THEN SomeValue ELSE 0 END) AS Expenditure)
FROM
    MyTable
WHERE
    EmployeeID = @empID --optional for all employees
GROUP BY
    EmployeeID 
)
SELECT
    Income, Expenditure, Income - Expenditure
FROM
    cSUMs 

有一次,我从一个基于bog标准集合的聚合查询中消除了这种OO思维,从而将一个查询从一个周末缩短到了一秒钟以下。

忘记函数调用:您可能可以在一个普通查询中完成所有操作

函数调用被误用(试图进行OO封装)会迫使您陷入这种情况。此外,如果在Employee表中每行都有GetBalance(EmployeeID),则在该表上进行光标移动。而你现在也通过多次电话来解决这个问题

你需要的是这样的东西:

;WITH cSUMs AS
(
SELECT
    SUM(CASE WHEN type = 'Incomes' THEN SomeValue ELSE 0 END) AS Income),
    SUM(CASE WHEN type = 'Expenditures' THEN SomeValue ELSE 0 END) AS Expenditure)
FROM
    MyTable
WHERE
    EmployeeID = @empID --optional for all employees
GROUP BY
    EmployeeID 
)
SELECT
    Income, Expenditure, Income - Expenditure
FROM
    cSUMs 

有一次,我从一个基于bog标准集的聚合查询中消除了这种OO思维,从而将查询从一个周末缩短到了一秒钟以下。

您能在客户端代码中进行组合吗?此select语句是应用程序不同位置多次使用的视图的一部分。所以我认为将它包含在视图中是有意义的,这样我就不必在不同的地方重写相同的计算。毕竟,我认为这就是视图的全部目的。你能在客户端代码中进行组合吗?这个select语句是在应用程序的不同位置多次使用的视图的一部分。所以我认为将它包含在视图中是有意义的,这样我就不必在不同的地方重写相同的计算。毕竟我认为这就是视图的全部目的。对于OO封装评论,我会给你一百万分。当您尝试使用OO编程规则时,关系数据库的性能并不是最好的。我之所以在函数中包含这两个东西,是因为计算相当复杂,我需要在整个应用程序中的许多其他不同select语句中得到结果。因此,对我来说,只编写一次功能,然后重用它是有意义的。我想我不是唯一一个不喜欢一直重写相同代码的人。如果场景像您所指示的那样(只是一个带有CASE语句的简单select)来获得结果,我就不会为它编写函数。但事实并非如此。@Trex:那好吧。然后接受缓慢的性能,以避免对基于集合的操作进行优化。就这么简单,我不明白。那么,您的意思是,为了获得更好的性能,我必须在每个需要它的查询中重写相同的代码?如果这是获得更好表现的唯一途径,我不妨这样做。我只是想确定这就是你所说的…@Trex:不是在每个查询中都是这样的:只是在需要在多行上运行它的地方。对于一个员工,我会把它放在一个UDFI中,对于OO封装评论,我会给你一百万分。当您尝试使用OO编程规则时,关系数据库的性能并不是最好的。我之所以在函数中包含这两个东西,是因为计算相当复杂,我需要在整个应用程序中的许多其他不同select语句中得到结果。因此,对我来说,只编写一次功能,然后重用它是有意义的。我想我不是唯一一个不喜欢一直重写相同代码的人。如果场景像您所指示的那样(只是一个带有CASE语句的简单select)来获得结果,我就不会为它编写函数。但事实并非如此。@Trex:那好吧。然后接受缓慢的性能,以避免对基于集合的操作进行优化。就这么简单,我不明白。那么,您的意思是,为了获得更好的性能,我必须在每个需要它的查询中重写相同的代码?如果这是获得更好表现的唯一途径,我不妨这样做。我只是想确定这就是你所说的…@Trex:不是在每个查询中都是这样的:只是在需要在多行上运行它的地方。对于一个员工,我会把它放在UDF中