我正在努力加快查询速度。我需要每行运行2个标量值函数,并将几列作为参数。
这些函数根据运行总计进行计算,并且在SQL Server 2008中没有简单的方法(我很清楚)。
我的查询的CTE部分获取了我需要计算的所有行,并且需要为每个级别单独运行。客户与商店之间的关系是一对多的,但您无法根据其每个商店计算在客户端级别(Store =' All')进行计算。
我的第一次尝试是在' SELECT'中使用函数调用。声明,但我读到他们会同步运行,这是没有必要的。下面的尝试试图将计算转换为表值,以尝试异步运行它们。
我想知道OUTER APPLY是否可行,或者是否有更有效的方法来解决这个问题。
如果需要更多信息,请与我们联系!
DECLARE @StartTime INT
SET @StartTime=20170101
DECLARE @EndTime INT
SET @EndTime=20170131
;WITH IsAvgStores AS (
SELECT
COALESCE(ParentClient,'All') AS ParentClient,
COALESCE(Client,'All') AS Client,
COALESCE(Store,'All') AS Store,
MAX(Answer_Threshold),
MAX(SL_Threshold)
FROM
client_hierarchy
WHERE
GETDATE() BETWEEN EFF_BEGIN_DATE AND EFF_END_DATE
GROUP BY ROLLUP(ParentClient,Client,Store)
)
SELECT I.ParentClient,I.Client,I.Store
,SL.isAvg_SL_String
,A.isAvg_ASA_String
INTO #isAvgTemp
FROM IsAvgStores I
OUTER APPLY ( SELECT dbo.isAvg_S_B(ParentClient,Client,Store,Answer_Threshold,@StartTime,@EndTime) AS isAvg_SL_String
) SL
OUTER APPLY ( SELECT dbo.isAvg_A_B(ParentClient,Client,Store,SL_Threshold,@StartTime,@EndTime) AS isAvg_ASA_String
) A
WHERE ParentClient<>'All'
SELECT *
FROM #isAvgTemp
答案 0 :(得分:5)
评论太长了。
对于标量值函数,outer apply
是多余的。你可以这样做:
SELECT I.ParentClient, I.Client, I.Store,
dbo.isAvg_S_B(ParentClient, Client, Store,A nswer_Threshold, @StartTime, @EndTime) AS isAvg_SL_String,
dbo.isAvg_A_B(ParentClient, Client, Store, SL_Threshold, @StartTime, @EndTime) as isAvg_ASA_String
INTO #isAvgTemp
FROM IsAvgStores I
WHERE ParentClient <> 'All';
这对性能完全没有影响;它只是简化了查询。
为了提高性能,您有三种选择:
outer apply
作为运行总和。这些都不是最佳选择。如果个别群体很小,前两个可能会有效。第三种可能是这种情况下的最佳选择 - 请注意我非常厌恶游标。
或者,您最好的选择:升级到更高版本的SQL Server并使用SQL Server 2012 +中提供的累积和函数。
答案 1 :(得分:0)
另一种选择是尝试将标量函数转换为返回标量值的inline table-valued functions(ITVF)。这可能适用于您的方案,也可能不适用。根据我的经验,complex scalar functions generally perform poorly in SQL Server on larger result sets因为他们运行RBAR。使用ITVF,SQL Server能够内联查询以优化查询计划。
您的查询看起来类似于您尝试使用OUTER APPLY
完成的内容:
SELECT I.ParentClient, I.Client, I.Store, SL.isAvg_SL_String A.isAvg_ASA_String
INTO #isAvgTemp
FROM IsAvgStores I
OUTER APPLY dbo.isAvg_S_B(ParentClient,Client,Store,Answer_Threshold,@StartTime,@EndTime)SL
OUTER APPLY dbo.isAvg_A_B(ParentClient,Client,Store,SL_Threshold,@StartTime,@EndTime) A
WHERE ParentClient <> 'All';
不同之处在于您的函数将返回一个包含单个结果的表:
CREATE FUNCTION dbo.isAvg_S_B (...)
RETURNS TABLE
AS
(
SELECT ... AS 'isAvg_SL_String'
FROM ...
);
同样,这可能会或可能不会提高您的特定情况下的性能,但我认为值得一提以防止重复代码。