Quantcast
Channel: Transact-SQL forum
Viewing all articles
Browse latest Browse all 23857

Optimize a correlated subquery

$
0
0

I have a test subquery here. You can just run it as is in SSMS. I am trying to get a LAST payment date and a and a LAST payment amount and I think I am getting it. The problem is that the way it is written, when I run it on a real dataset, it is slow, and when since I have to add more sub-queries and columns, it will be even worse. I figured I could use a join somehow and query the columns that way. Or maybe there is a superior way. I am looking for ideas as there are a lot of columns that need some kind of calculation or a sub-query to get the maximum or minimum or count or sum of something. My example here is just a model, but hopefully one that I can adapt to my much larger query:

CREATE TABLE #h
(
 ACCT_ID INT IDENTITY(1,1)
,ACCT_NO VARCHAR(10)
,PMT_AMT SMALLMONEY
,PMT_DATE DATE
)

CREATE TABLE #a
(
 ACCT_ID INT IDENTITY(1,1)
,ACCT_NO VARCHAR(10)
,LAST_PMT_AMT SMALLMONEY
,LAST_PMT_DATE DATE
)

INSERT INTO #a ( ACCT_NO ) VALUES  ( '1')
INSERT INTO #a ( ACCT_NO ) VALUES  ( '2')
INSERT INTO #a ( ACCT_NO ) VALUES  ( '3')
INSERT INTO #a ( ACCT_NO ) VALUES  ( '4')
INSERT INTO #a ( ACCT_NO ) VALUES  ( '5')
INSERT INTO #a ( ACCT_NO ) VALUES  ( '6')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 200,'2013-09-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 300,'2013-09-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 400,'2013-09-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 450,'2013-09-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 500,'2013-09-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '1', 600,'2013-09-05')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '2', 1200,'2013-08-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '2', 1300,'2013-08-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '2', 1400,'2013-08-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '2', 1500,'2013-08-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '2', 1600,'2013-08-05')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '3', 2200,'2013-07-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '3', 2300,'2013-07-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '3', 2400,'2013-07-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '3', 2500,'2013-07-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '3', 2600,'2013-07-05')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '4', 200,'2012-09-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '4', 300,'2012-09-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '4', 400,'2012-09-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '4', 500,'2012-09-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '4', 600,'2012-09-05')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '5', 1200,'2012-08-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '5', 1300,'2012-08-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '5', 1400,'2012-08-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '5', 1500,'2012-08-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '5', 1600,'2012-08-05')

INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '6', 2200,'2012-07-01')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '6', 2300,'2012-07-02')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '6', 2400,'2012-07-03')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '6', 2500,'2012-07-04')
INSERT INTO #h ( ACCT_NO, PMT_AMT, PMT_DATE ) VALUES  ( '6', 2600,'2012-07-05')

SELECT
	 1 'QueryNo'
	,'Table #h Initial Values' Notes
	,ACCT_ID
	,ACCT_NO  
	,PMT_AMT  
	,PMT_DATE 
FROM #h

SELECT 
	 2 'QueryNo'
	,'Table #a Initial Values' Notes
	,ACCT_ID
	,ACCT_NO  
	,LAST_PMT_AMT  
	,LAST_PMT_DATE 
FROM #a

SELECT 
	 3 'QueryNo'
	,'Table #a LAST_PMT Values prior to insert' Notes
	,ACCT_ID
	,ACCT_NO  
    ,LAST_PMT_AMT  = (SELECT #h.PMT_AMT  FROM #h WHERE #h.PMT_DATE = (SELECT MAX(PMT_DATE) FROM #h WHERE #h.ACCT_NO = #a.ACCT_NO))
	,LAST_PMT_DATE = (SELECT #h.PMT_DATE FROM #h WHERE #h.PMT_DATE = (SELECT MAX(PMT_DATE) FROM #h WHERE #h.ACCT_NO = #a.ACCT_NO))
FROM #a


UPDATE #a
SET  LAST_PMT_AMT  = (SELECT #h.PMT_AMT  FROM #h WHERE #h.PMT_DATE = (SELECT MAX(PMT_DATE) FROM #h WHERE #h.ACCT_NO = #a.ACCT_NO))
	,LAST_PMT_DATE = (SELECT #h.PMT_DATE FROM #h WHERE #h.PMT_DATE = (SELECT MAX(PMT_DATE) FROM #h WHERE #h.ACCT_NO = #a.ACCT_NO))

SELECT 
	 4 'QueryNo'
	,'Table #a LAST_PMT Values after insert' Notes
	,ACCT_ID
	,ACCT_NO  
	,LAST_PMT_AMT  
	,LAST_PMT_DATE 
FROM #a

SELECT 
	 5 'QueryNo'
	,'Table #h Initial Values - repeated for comparison' Notes
	,ACCT_ID
	,ACCT_NO  
	,PMT_AMT  
	,PMT_DATE 
FROM #h

DROP TABLE #h
DROP TABLE #a

Thank you.



Viewing all articles
Browse latest Browse all 23857

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>