SQL Server子查询别名不能使用,当前代码很慢

问题描述 投票:0回答:1

我有以下数据和代码。我所追求的是根据汇总表中的日期获得用户的先前余额,然后从活动表中获取前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%模仿我的问题

sql sql-server
1个回答
0
投票

你可以使用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(技术上是横向连接)很有趣,因为这是一个非常强大的运算符。

© www.soinside.com 2019 - 2024. All rights reserved.