我有一个使用while循环临时表和游标的存储过程,通过它可以获得客户的老化平衡,但是我的SP工作正常,但我有一些性能问题,因为它需要15秒才能产生小的结果大块的数据。我正在寻找一种更有效的方法来实现这一目标。
提前致谢。
这是我的存储过程。
CREATE TABLE #Customer_Temp (
AccountCode varchar(50),
AccountTitle varchar(50),
CurrentBalance int,
FirstBalance int,
SecondBalance int,
ThirdBalance int,
FourthBalance int,
FifthBalance int,
SixthBalance int,
SeventhBalance int,
EighthBalance int,
OpeningBalance int
)
INSERT INTO #customer_temp (AccountCode, AccountTitle, OpeningBalance)
SELECT
Customer.AccountCode,
Customer.Name,
COA.OpeningBalance
FROM Customers AS Customer
INNER JOIN ChartOfAccount AS COA
ON COA.CompanyId = @Companyid
AND COA.BusinessUnitId = @BusinessUnitId
AND COA.ChartAccount = Customer.AccountCode
--Create Table And Duplicate Customers Data In it ENDED
DECLARE @DrAmount AS int
DECLARE @CrAmount AS int
DECLARE @Balance AS int
DECLARE @FBalance AS int
DECLARE @SBalance AS int
DECLARE @TBalance AS int
DECLARE @FoBalance AS int
DECLARE @FIBalance AS int
DECLARE @SIBalance AS int
DECLARE @SEBalance AS int
DECLARE @EBalance AS int
DECLARE @FSDate AS date
DECLARE @FLDate AS date
DECLARE @SSDate AS date
DECLARE @SLDate AS date
DECLARE @TSDate AS date
DECLARE @TLDate AS date
DECLARE @FOSDate AS date
DECLARE @FOLDate AS date
DECLARE @FISDate AS date
DECLARE @FILDate AS date
DECLARE @SISDate AS date
DECLARE @SILDate AS date
DECLARE @SESDate AS date
DECLARE @SELDate AS date
DECLARE @ESDate AS date
SET @FSDate = DATEADD(DAY, -1, @StartDate)
SET @FLDate = DATEADD(DAY, -6, @FSDate)
SET @SSDate = DATEADD(DAY, -1, @FLDate)
SET @SLDate = DATEADD(DAY, -6, @SSDate)
SET @TSDate = DATEADD(DAY, -1, @SLDate)
SET @TLDate = DATEADD(DAY, -14, @TSDate)
SET @FOSDate = DATEADD(DAY, -1, @TLDate)
SET @FOLDate = DATEADD(DAY, -14, @FOSDate)
SET @FISDate = DATEADD(DAY, -1, @FOLDate)
SET @FILDate = DATEADD(DAY, -14, @FISDate)
SET @SISDate = DATEADD(DAY, -1, @FILDate)
SET @SILDate = DATEADD(DAY, -29, @SISDate)
SET @SESDate = DATEADD(DAY, -1, @SILDate)
SET @SELDate = DATEADD(DAY, -89, @SESDate)
SET @ESDate = DATEADD(DAY, -1, @SELDate)
DECLARE @TempCCode AS varchar(50)
DECLARE @TempOBalance AS float
DECLARE CustomerCursor CURSOR FOR
SELECT
AccountCode,
OpeningBalance
FROM #Customer_Temp
OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO @TempCCode, @TempOBalance
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @FBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FSDate,
@FLDate,
@Fyear
EXEC @SBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SSDate,
@SLDate,
@Fyear
EXEC @TBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@TSDate,
@TLDate,
@Fyear
EXEC @FoBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FOSDate,
@FOLDate,
@Fyear
EXEC @FIBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FISDate,
@FILDate,
@Fyear
EXEC @SIBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SISDate,
@SILDate,
@Fyear
PRINT @SESDate
PRINT @SELDate
EXEC @SEBalance =
GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SESDate,
@SELDate,
@Fyear
EXEC @EBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@ESDate,
@EndDate,
@Fyear
EXEC @Balance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@StartDate,
@EndDate,
@Fyear
UPDATE #Customer_Temp
SET CurrentBalance = (@Balance + @TempOBalance),
FirstBalance = @FBalance,
SecondBalance = @SBalance,
ThirdBalance = @TBalance,
FourthBalance = @FoBalance,
FifthBalance = @FIBalance,
SixthBalance = @SIBalance,
SeventhBalance = @SEBalance,
EighthBalance = @EBalance
WHERE AccountCode = @TempCCode
FETCH NEXT FROM CustomerCursor INTO @TempCCode, @TempOBalance
END
CLOSE CustomerCursor
DEALLOCATE CustomerCursor
这里是游标
中的被调用存储过程CREATE PROCEDURE [dbo].[GetBalanceOfAgingOnDate]
@BusinessUnitId int,
@Companyid int,
@ChartAccount as varchar (50),
@StartDate as DateTime,
@EndDate as DateTime,
@Fyear as varchar(50)
AS BEGIN
Declare @DrAmount as int
Declare @CrAmount as int
Declare @Balance as int
set @DrAmount=(select sum(Dr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = @Companyid AND
AM.BusinessUnitId = @BusinessUnitId AND AM.FYear = @Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=@ChartAccount AND
AC.CreatedOn Between @EndDate AND @StartDate);
set @CrAmount=(select sum(Cr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = @Companyid AND
AM.BusinessUnitId = @BusinessUnitId AND AM.FYear = @Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=@ChartAccount AND
AC.CreatedOn Between @EndDate AND @StartDate);
set @Balance = @DrAmount - @CrAmount ;
return ISNULL(@Balance,0)
END
答案 0 :(得分:1)
答案 1 :(得分:0)
你的问题是你不认为SQL并试图变得聪明 - 你编写过程代码,SQL Server必须逐个执行INSTEAD才能在set中工作并让查询优化器弄清楚如何最有效地执行
游标和程序通常是缓慢的元素。您最好在尽可能少的原子SQL语句中对此进行讨论,即使语句是一页或两页长。然后查询优化器可以弄清楚如何最有效地实现这个结果。
在你的情况下,第二个SP在光标中被重复调用 - 有可能更好地实现这一点。在一个或更少的电话中。
答案 2 :(得分:0)
希望这可以让你走上正轨。你的问题有很多,所以我可能不会(a)理解这里的一切,(b)解决每个部分,但希望你能从这里开始。我没有看到任何程序或循环的需要。尝试一下,我已经评论了一些上下文:
/* Construct a temp table to store all balance dates (and respective names) */
CREATE TABLE #BalanceDates (BalanceName VARCHAR(20), StartDate DATETIME, EndDate DATETIME);
INSERT INTO BalanceDates VALUES ('FirstBalance',DATEADD(DAY,-1,@StartDate),DATEADD(DAY,-6,@StartDate));
-- And so on with remaining inserts...
/* Create a denormalized table of all balances */
SELECT
[FirstBalance],
[SecondBalance],
...
INTO
#Balances
FROM
(
SELECT
BD.BalanceName,
ISNULL(SUM(Dr_Amount) - SUM(Cr_Amount),0) AS BalanceAmount
FROM
#BalanceDates BD
LEFT JOIN
AccountVocherChild AC
ON (AC.CreatedOn BETWEEN BD.StartDate AND BD.EndDate)
LEFT JOIN
AccountVocherMaster AM
ON (AM.VocherId = AC.VocherId)
WHERE
AM.CompanyId = @Companyid AND
AM.BusinessUnitId = @BusinessUnitId AND
AM.FYear = @Fyear AND
AC.AccountCode = @ChartAccount
GROUP BY
BD.BalanceName
) data
PIVOT
(
AVG(BalanceAmount)
FOR BalanceName IN ([FirstBalance],[SecondBalance],...)
) pvt;
/* Update the table accordingly */
UPDATE tgt
SET
FirstBalance = src.FirstBalance,
SecondBalance = src.SecondBalance,
...
FROM #Customer_Temp tgt
JOIN #Balances src
ON (1 = 1);