I have following data and code. What I am after is to get previous balance for a user based upon a date in summary table and then get the top 1 record from activity table where date is less than summary date. The code I have seems to give me the results needed, however, there is a big issue. My piece of code is extremely slow as there are 100s of thousands of rows in database and there could be any number of records which are less than a summary date. I tried to use joins and sub query but was getting errors that I could not use alias in subquery. Hope my question makes sense and some one can guide. Thanks Here is sample data and my query
if object_id('tempdb..#tsummary') is not null drop table #tsummary;
if object_id('tempdb..#tactivity') is not null drop table #tactivity;
--Temp tables to hold test data
CREATE TABLE #tsummary(
[accountname] [char](8) NULL,
[lastdepodate] [datetime] NULL,
[depositAmount] [int] NULL,
[currentBal] [int] NULL,
[prevBal] [int] NOT NULL
)
CREATE TABLE #tactivity(
[accountName] [char](8) NULL,
[activitydate] [datetime] NULL,
[debitAmount] [money] NULL,
[balance] [int] NULL
)
--Insert test data for table 1
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User1 ', CAST(N'2018-01-25 16:09:05.000' AS DateTime), 20, 20, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User1 ', CAST(N'2018-01-06 17:43:58.000' AS DateTime), 20, 20, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User1 ', CAST(N'2018-01-05 22:39:46.000' AS DateTime), 3160, 3160, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User1 ', CAST(N'2018-01-04 16:45:30.000' AS DateTime), 3000, 3000, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User2 ', CAST(N'2017-10-06 11:33:54.000' AS DateTime), 6000, 6000, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User2 ', CAST(N'2017-10-06 11:23:20.000' AS DateTime), 4000, 20, 0);
INSERT #tsummary ([accountname], [lastdepodate], [depositAmount], [currentBal], [prevBal]) VALUES (N'User2 ', CAST(N'2017-09-24 10:48:49.000' AS DateTime), 500, 500, 0);
--Insert test data for table 1
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 17:43:58.000' AS DateTime), 0.0000, 20);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:41:26.000' AS DateTime), 120.0000, 1720);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:41:26.000' AS DateTime), 60.0000, 1660);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:28:32.000' AS DateTime), 60.0000, 1780);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:27:07.000' AS DateTime), 60.0000, 1840);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:25:54.000' AS DateTime), 60.0000, 1900);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:10:31.000' AS DateTime), 60.0000, 1920);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User1 ', CAST(N'2018-01-06 03:10:31.000' AS DateTime), 20.0000, 1900);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-06 11:23:20.000' AS DateTime), 0.0000, 20);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-05 15:41:46.000' AS DateTime), 400.0000, 420);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-04 17:03:16.000' AS DateTime), 100.0000, 520);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-04 13:25:06.000' AS DateTime), 400.0000, 920);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-04 13:20:45.000' AS DateTime), 120.0000, 1040);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-03 16:58:57.000' AS DateTime), 20.0000, 1060);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-03 11:26:24.000' AS DateTime), 200.0000, 1260);
INSERT #tactivity ([accountName], [activitydate], [debitAmount], [balance]) VALUES (N'User2 ', CAST(N'2017-10-01 13:11:51.000' AS DateTime), 100.0000, 1360);
--Following is my query which gives me prev balance
select mqry.accountName,mqry.lastDepoDate,mqry.depositAmount,mqry.currentBal,ISNULL(
(select top 1 subq.balance from #tactivity subq where subq.accountName=mqry.accountName and subq.activityDate <mqry.lastDepoDate order by subq.activityDate desc)
,0) prevBal
from #tsummary mqry;
The above query will give me following output
accountName lastDepoDate depositAmount currentBal prevBal
User1 2018-01-25 16:09:05.000 20 20 20
User1 2018-01-06 17:43:58.000 20 20 1660
User1 2018-01-05 22:39:46.000 3160 3160 0
User1 2018-01-04 16:45:30.000 3000 3000 0
User2 2017-10-06 11:33:54.000 6000 6000 20
User2 2017-10-06 11:23:20.000 4000 20 420
User2 2017-09-24 10:48:49.000 500 500 0
I have played around with joins and using subquery. But always get error as I must compare subquery with accountname and date from main query. Thanks for your suggestions in advance. Please pardon for lots of sample code, it is so that I can mimic my issue 100%
You can use outer apply
:
select mqry.accountName, mqry.lastDepoDate, mqry.depositAmount, mqry.currentBal,
coalesce(subq.balance, 0) as prevBal
from #tsummary mqry outer apply
(select top 1 subq.balance
from #tactivity subq
where subq.accountName = mqry.accountName and subq.activityDate < mqry.lastDepoDate
order by subq.activityDate desc
) subq;
Then, for this query, you want an index on #tactivity
:
create index idx_tactivity_accountName_activityDate_balance on #tactivity(accountName, activityDate, balance);
Actually, the index will help the subquery alone. But, it is fun to learn about apply
(technically a lateral join ), because this is a very powerful operator.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.