Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
Rasta Pickles
Posting Yak Master
174 Posts |
Posted - 2012-08-19 : 12:05:26
|
Apologies, I've inherited this so I don't know whether it's phenomenally inefficient or as good as it gets.It involves three tables; AGREEMENTS contains 700,000 records, AGREEMENT_PROFILES contains 7,000,000 records and TRANSACTION_HEADER contains 9,500,000 records.Retrieving data for two days takes 11 minutes.DECLARE @StartDate DATE, @StopDate DATESET @StartDate = '2012-06-30' --change as necessarySET @StartDate = DATEADD(DAY, 1, @StartDate)SET @StopDate = '2013-01-01' --change as necessaryDECLARE @test AS TABLE (DATEX DATETIME, FINANCIER_ID INT, OUTSTANDING_LOAN_TOTAL DECIMAL(12,2))WHILE @StartDate < @StopDateBEGININSERT INTO @testSELECT @StartDate AS DATEX, FINANCIER_ID, SUM(CASE WHEN TH.TRANSACTION_TYPE_ID IN (1,2) THEN ISNULL(TH.PREMIUM_VALUE,0) ELSE (ISNULL(TH.PREMIUM_VALUE,0) ) * -1 END) AS OUTSTANDING_LOAN_TOTAL FROM AGREEMENTS AS AG INNER JOIN TRANSACTION_HEADER AS TH ON TH.AGREEMENT_ID = AG.AGREEMENT_ID WHERE ( AG.CANCELLATION_DATE IS NULL OR AG.CANCELLATION_DATE > @StartDate ) AND (AG.RETIRED_DATE IS NULL OR AG.RETIRED_DATE > @StartDate) AND TH.TRANSACTION_TYPE_ID IN (1, 2, 4, 9, 10, 20, 21, 24) AND TH.EFFECTIVE_DATE < @StartDate AND TH.AGREEMENT_ID IN (SELECT APX.AGREEMENT_ID FROM AGREEMENT_PROFILES AS APXJOIN AGREEMENTS AS AX ON AX.AGREEMENT_ID = APX.AGREEMENT_IDWHERE APX.DUE_DATE < @StartDateAND (APX.PAID_DATE IS NULL OR APX.PAID_DATE >= @StartDate)AND APX.CHARGE_NUMBER IS NULLAND (AX.CANCELLATION_DATE IS NULL OR AX.CANCELLATION_DATE >= @StartDate)AND APX.AGREEMENT_ID IN (SELECT TOP 1 THX.AGREEMENT_ID FROM TRANSACTION_HEADER AS THX WHERE THX.AGREEMENT_ID = APX.AGREEMENT_ID AND THX.INSTALMENT_NUMBER = APX.INSTALMENT_NUMBER AND THX.CHARGE_NUMBER IS NULL AND THX.TRANSACTION_TYPE_ID IN (10, 20)AND THX.EFFECTIVE_DATE < @StartDate)AND 24 <> (SELECT TOP 1 THX.TRANSACTION_TYPE_ID FROM TRANSACTION_HEADER AS THX WHERE THX.AGREEMENT_ID = APX.AGREEMENT_ID AND THX.INSTALMENT_NUMBER = APX.INSTALMENT_NUMBER AND THX.CHARGE_NUMBER IS NULL AND THX.EFFECTIVE_DATE < @StartDateORDER BY EFFECTIVE_DATE DESC))GROUP BY FINANCIER_IDSET @StartDate = DATEADD(DAY, 1, @StartDate)ENDselect * from @test Thanks in advance. |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-08-19 : 13:52:02
|
| i see lot of subqueries which can be an issue especially in case of large datasets------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Rasta Pickles
Posting Yak Master
174 Posts |
Posted - 2012-08-19 : 14:04:54
|
| Well 11 minutes to retrieve 2 days worth of data would seem, by virtue of that elongated duration, to vindicate what you are alluring to.Any suggestions? |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-08-19 : 14:28:21
|
| try changing them to joins------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Rasta Pickles
Posting Yak Master
174 Posts |
Posted - 2012-08-19 : 14:32:27
|
Thank you for your guidance.Given that this forum is a "new to SQL Server programming", you might have well told me to program a probe to land on the moon But I will take your advice, thank you again |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2012-08-19 : 17:05:36
|
There are two things you see in your query that slows it down. One is the loop. You should be able to get all the data in one query instead of having to loop through it. Second is the the subqueries. It should be possible to join the tables rather than have a subquery.Given below is an attempt to remove the loops. What I am trying to do is to create a calendar table and then join to it. But this may be completely wrong because I don't have any test data to test and I don't really understand the logic.If you choose to use it, first change the start date and end date to be the same or different by just one day. See if that gives you the right results. If it does, then make it a two-day difference and see if that works. Regarding the subquery, it takes too much thinking (on my part) to figure it out :) If this improves the performance, you may not need it.DECLARE @StartDate DATE, @StopDate DATESET @StartDate = '2012-06-30' --change as necessarySET @StartDate = DATEADD(DAY, 1, @StartDate)SET @StopDate = '2013-01-01' --change as necessaryCREATE TABLE #Calendar(Dt DATETIME NOT NULL PRIMARY KEY CLUSTERED);;WITH N(n) AS( SELECT 1 UNION ALL SELECT n+1 FROM N WHERE n <= DATEDIFF(dd,@StartDate,@StopDate))INSERT INTO #Calendar SELECT DATEADD(dd,n-1,@StartDate) FROM NOPTION (MAXRECURSION 0);--WHILE @StartDate < @StopDate--BEGIN-- INSERT INTO @test SELECT Dt AS DATEX, FINANCIER_ID, SUM( CASE WHEN TH.TRANSACTION_TYPE_ID IN (1, 2) THEN ISNULL(TH.PREMIUM_VALUE, 0) ELSE (ISNULL(TH.PREMIUM_VALUE, 0)) * -1 END ) AS OUTSTANDING_LOAN_TOTAL FROM AGREEMENTS AS AG INNER JOIN TRANSACTION_HEADER AS TH ON TH.AGREEMENT_ID = AG.AGREEMENT_ID CROSS JOIN #Calendar WHERE ( AG.CANCELLATION_DATE IS NULL OR AG.CANCELLATION_DATE > Dt ) AND (AG.RETIRED_DATE IS NULL OR AG.RETIRED_DATE > Dt) AND TH.TRANSACTION_TYPE_ID IN (1, 2, 4, 9, 10, 20, 21, 24) AND TH.EFFECTIVE_DATE < Dt AND TH.AGREEMENT_ID IN (SELECT APX.AGREEMENT_ID FROM AGREEMENT_PROFILES AS APX JOIN AGREEMENTS AS AX ON AX.AGREEMENT_ID = APX.AGREEMENT_ID WHERE APX.DUE_DATE < Dt AND (APX.PAID_DATE IS NULL OR APX.PAID_DATE >= Dt) AND APX.CHARGE_NUMBER IS NULL AND ( AX.CANCELLATION_DATE IS NULL OR AX.CANCELLATION_DATE >= Dt ) AND APX.AGREEMENT_ID IN (SELECT TOP 1 THX.AGREEMENT_ID FROM TRANSACTION_HEADER AS THX WHERE THX.AGREEMENT_ID = APX.AGREEMENT_ID AND THX.INSTALMENT_NUMBER = APX.INSTALMENT_NUMBER AND THX.CHARGE_NUMBER IS NULL AND THX.TRANSACTION_TYPE_ID IN (10, 20) AND THX.EFFECTIVE_DATE < Dt) AND 24 <> ( SELECT TOP 1 THX.TRANSACTION_TYPE_ID FROM TRANSACTION_HEADER AS THX WHERE THX.AGREEMENT_ID = APX.AGREEMENT_ID AND THX.INSTALMENT_NUMBER = APX.INSTALMENT_NUMBER AND THX.CHARGE_NUMBER IS NULL AND THX.EFFECTIVE_DATE < Dt ORDER BY EFFECTIVE_DATE DESC )) GROUP BY FINANCIER_IDDROP TABLE #Calendar; -- SET @StartDate = DATEADD(DAY, 1, @StartDate)--END--SELECT *--FROM @test |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2012-08-20 : 03:24:25
|
Which version of SQL Server are you using? N 56°04'39.26"E 12°55'05.63" |
 |
|
|
|
|
|
|
|