我有一个搜索程序需要使用特定的价格类型返回结果。此类价格类型(取决于授予搜索者访问权限的客户)是计算价格。我们使用UDF来计算这个价格。因此,根据提交的搜索,可能会有许多不同的价格回来。除了搜索的价格类型之外,我们还需要按FROM和TO价格以及销售保证金范围过滤结果。
这是简化的,但基本上搜索看起来像这样......
SELECT Name, Model, f_GetPrices(modelID, @userID, priceType)
FROM products
WHERE f_GetPrices(modelID, @userID priceType) Between @from and @to
AND (RetailPrice-f_GetPrices(modelID, @userID, priceType) / Retail Price * 100) Between @fromMargin and @toMargin
问题是我每条记录都要调用这个UDF 4次。
这是一个简化版本,通常我将所有结果都插入临时表中。然后我使用@pageSize和@pageNumber拉出我想要的页面,在第二个结果中,我返回返回的总行数。这允许我们的UI进行分页并显示总记录数。
我已经考虑将计算出的价格转储到临时表中,然后在从那里拉出的SELECT中执行我的WHERE子句。但是,由于我已经在进行分页,我实际上需要将所有具有计算价格的记录转储到临时表中,然后只提取价格范围内的那些记录,然后拉出最后一次分页和总记录,这样两个临时结果表。
我正试图找出最佳方法。
如果我在select中调用UDF 4次,那么SQL引擎是运行4次还是仅计算一次并使用它会导致每个记录的所有4个位置?
如果我选择了10,000条记录,其中只有100条符合价格标准(From,To,FromMargin,ToMargin),那么这些10k记录只能抓住100就好了。这就是为什么我试图申请价格范围为初始选择。但后来我认为SQL需要对所有10k记录进行计算才能应用WHERE子句。计算价格范围是否与计算价格范围相同,转储到临时表中,然后再次选择它?
答案 0 :(得分:0)
只需使用子查询:
select *
from (SELECT Name, Model, f_GetPrices(modelID, @userID, priceType) as fgp
FROM products
) p
WHERE fgp Between @from and @to and
(RetailPrice-fgp) / RetailPrice * 100) Between @fromMargin and @toMargin;
我还略微修改了最后一个条件的逻辑,因此差异除以RetailPrice
。
答案 1 :(得分:0)
如果您在此处优化性能,请尝试将f_GetPrices()
重写为内联表值函数而不是标量函数。标量函数通常是RBAR。
http://sqlmag.com/sql-server/inline-scalar-functions
您修改后的查询将如下所示:
SELECT
Name, Model, Price
FROM products
CROSS APPLY tvf_GetPrices(modelID, @userID, priceType) f
WHERE Price Between @from and @to
AND (RetailPrice - Price) / Retail Price * 100 Between @fromMargin and @toMargin
您的函数定义如下所示:
CREATE FUNCTION [dbo].[tvf_GetPrices](
@modelId int,
@userID int,
@priceType int
)
RETURNS TABLE
RETURN (
SELECT foo AS Price
FROM bar
WHERE @modelId
etc
)