我有以下数据和代码。我所追求的是根据汇总表中的日期获得用户的先前余额,然后从活动表中获取前1个记录,其中日期小于汇总日期。我的代码似乎给了我所需的结果,但是,有一个大问题。我的代码片段非常慢,因为数据库中有数千行,并且可能有任何数量的记录小于汇总日期。我试图使用连接和子查询,但得到的错误,我不能在子查询中使用别名。希望我的问题有道理,有些人可以指导。谢谢这是示例数据和我的查询
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;
上面的查询将给我以下输出
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
我玩过连接和使用子查询。但总是会出错,因为我必须将子查询与主查询中的accountname和date进行比较。提前感谢您的建议。请原谅大量的示例代码,这样我就能100%模仿我的问题
你可以使用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;
然后,对于此查询,您需要#tactivity
上的索引:
create index idx_tactivity_accountName_activityDate_balance on #tactivity(accountName, activityDate, balance);
实际上,索引将仅帮助子查询。但是,了解apply
(技术上是横向连接)很有趣,因为这是一个非常强大的运算符。