Abu*_*iaz 1 sql t-sql sql-server
嗨,我陷入了这个问题,我在SQL SERVER中通过CURSOR工作了一个解决方案,但是我的行大约是40万,并且输出要花费数小时,有人可以更快地做到这一点吗?也许通过CROSS APPLY或其他方式。谢谢
问题:仅需要对事务状态“已拒绝”进行计数,如果TransactionStatus为“已批准”,则计数器将重置为零。
交易记录
帐号卡号交易状态输入日期 10845522-XYZ 5471XXXXXXXX1111已批准10/09/2013 10845522-XYZ 5471XXXXXXXX1111拒绝10/09/2014 10845522-XYZ 5471XXXXXXXX1111拒绝10/09/2015 10845522-XYZ 5471XXXXXXXX9999已批准10/09/2016 10845522-ABC 5471XXXXXXXX6666拒绝10/09/2012 10845522-ABC 5471XXXXXXXX6666拒绝10/09/2019 10845522-DEF 5471XXXXXXXX7777拒绝10/09/2016 10845522-DEF 5471XXXXXXXX7777已批准10/09/2019
需要的输出
帐号卡号拒绝计数器修改日期 10845522-XYZ 5471XXXXXXXX1111 2 10/09/2015 10845522-XYZ 5471XXXXXXXX9999 0 2016年10月9日 10845522-ABC 5471XXXXXXXX6666 2 10/09/2019 10845522-DEF 5471XXXXXXXX7777 0 10/09/2019
我的带有游标和合并语句的代码/方法,可以正常工作,但是由于CURSOR而需要花费数小时才能完成
-- Main Transaction Table
Select row_number() Over(Order by EntryDate) RowNumber
,Account, CARD_NUMBER, TransactionStatus, EntryDate
into dbo.TransactionLog_Temp
from dbo.TransactionLog
-- Cursor
DECLARE @RowNumber AS INT
DECLARE C CURSOR FOR
Select Rownumber from dbo.TransactionLog_Temp order by Rownumber ASC
OPEN C
FETCH NEXT FROM C INTO @RowNumber;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Decide Update or Insert
MERGE INTO dbo.Declined_Counter_Table AS T
USING (Select Account,TransactionStatus,CARD_NUMBER,EntryDate
from TransactionLog_Temp where Rownumber=@RowNumber) S ON T.Account=S.Account AND T.CARD_NUMBER=S.CARD_NUMBER
WHEN MATCHED AND T.ModifiedDate<>S.EntryDate
THEN UPDATE SET T.[Counter] = CASE WHEN S.TransactionStatus ='Declined' THEN ISNULL(T.[Counter],0) + 1
WHEN S.TransactionStatus ='Approved' THEN 0 END
,T.ModifiedDate = S.EntryDate
WHEN NOT MATCHED BY TARGET AND S.TransactionStatus ='Declined'
THEN INSERT VALUES (S.Account, S.CARD_NUMBER,1, S.EntryDate);
-- remove from main table, to resume the query anyother time since its taking too long
Delete from dbo.TransactionLog_Temp where Rownumber=@RowNumber
print @RowNumber
FETCH NEXT FROM C INTO @RowNumber;
END;
CLOSE C;
DEALLOCATE C;
Run Code Online (Sandbox Code Playgroud)
您似乎想要一个聚合:
Select Account, CARD_NUMBER,
sum(case when TransactionStatus = 'Declined' then 1 else 0 end) as num_all_declines,
sum(case when TransactionStatus = 'Declined' and
(EntryDate > last_approved_ed or last_approved_ed is null
)
then 1 else 0
end) as num_recent_declines,
max(EntryDate)
from (select tl.*,
max(case when TransactionStatus = 'Approved' then EntryDate end) over (partition by Account, CARD_NUMBER) as last_approved_ed
from dbo.TransactionLog tl) query
group by Account, CARD_NUMBER;
Run Code Online (Sandbox Code Playgroud)
这比尝试使用游标要快得多。