我正在尝试加快查询速度。我需要每行运行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

最佳答案

这个评论太长了。

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作为运行总和。
重写代码以删除功能;使用递归CTE作为运行总和。
重写代码以删除功能;使用游标作为运行总和。


这些都不是最优的。如果单个组很小,则前两个可能会起作用。在这种情况下,第三个可能是最好的选择-请注意,我非常讨厌光标。

或者,最好的选择是:升级到更高版本的SQL Server,并使用SQL Server 2012+中提供的累积总和功能。

10-08 07:57
查看更多