朋友:
我对SQL Server查询有疑问
对于DCFlg =' Credit',意味着客户在银行存钱,DCFlag ='借记卡'意味着客户从银行取款。
我想从交易记录中找到一些客户,如果客户在银行存了一些钱,并且在3天内没有提取一半。
以下是一些示例交易记录:
TransactionNo AccountNo DCFlag TransactionDateTime TransactionBaseAmount
A000001 A1 CREDIT 2015/9/17 16:24:11 $1,000
A000002 A1 DEBIT 2015/9/18 16:24:11 $200
A000003 A1 DEBIT 2015/9/19 16:24:11 $100
A000004 B1 DEBIT 2015/10/22 8:18:46 $1000
A000005 B1 CREDIT 2015/10/22 10:18:46 $500
A000006 C1 CREDIT 2015/10/22 8:18:46 $1,000
A000007 C1 DEBIT 2015/10/22 10:18:46 $900
A000008 C1 CREDIT 2015/10/22 18:18:46 $950
A000009 D1 DEBIT 2013/11/21 19:43:50 $1,000
A000010 D1 CREDIT 2013/11/21 20:43:50 $600
A000011 D1 DEBIT 2013/11/22 19:43:50 $400
我想要的结果是:
AccountNo
A1
B1
C1
我尝试了我的SQL:
WITH Cre AS
(
SELECT AccountNo,cast(TransactionDateTime as date) TxnDate,SUM(TransactionBaseAmount) Cre_Amount
FROM mytable
WHERE DCFlag = 'Credit'
group by AccountNo,cast(TransactionDateTime as date)
),
Deb AS
(
SELECT AccountNo,cast(TransactionDateTime as date) TxnDate,SUM(TransactionBaseAmount) Deb_Amount
FROM mytable
WHERE DCFlag = 'Debit'
group by AccountNo,cast([TransactionDateTime] as date)
)
SELECT A.AccountNo
FROM Cre A,
Deb D,
Deb E,
Deb F
WHERE A.TxnDate = DATEADD(D,1,E.TxnDate) AND A.TxnDate = DATEADD(D,2,F.TxnDate)
AND A.TxnDate = D.TxnDate
AND A.AccountNo = D.AccountNo
AND A.AccountNo = E.AccountNo
AND A.AccountNo = F.AccountNo
GROUP BY A.AccountNo,A.TxnDate,
D.AccountNo,D.TxnDate,
E.AccountNo,E.TxnDate,
F.AccountNo,F.TxnDate,
A.Cre_Amount,D.Deb_Amount,E.Deb_Amount,F.Deb_Amount
HAVING A.Cre_Amount>(D.Deb_Amount+E.Deb_Amount+F.Deb_Amount)/2
group by AccountNo
我得到了结果:
AccountNo
A1
C1
需求与结果之间差异的原因是 TransactionNo = A000004 ,因为它的DCFlag ='借记卡'我想要的是在顾客在银行存钱后,他在3天内不会取出一半。 当我发现这个问题时,我修改了我的SQL:
WITH Cre AS
(
SELECT AccountNo,TransactionDateTime,TransactionBaseAmount
FROM T_I_ACCOUNT_TRANSACTION
WHERE DCFlag = 'Credit'
),
Deb AS
(
SELECT AccountNo,TransactionDateTime,TransactionBaseAmount
FROM T_I_ACCOUNT_TRANSACTION
WHERE DCFlag = 'Debit'
)
SELECT A.AccountNo
FROM Cre A,
Deb D,
Deb E,
Deb F
WHERE cast(A.TransactionDateTime as date) = DATEADD(D,1,cast(E.TransactionDateTime as date))
AND cast(A.TransactionDateTime as date) = DATEADD(D,2,cast(F.TransactionDateTime as date))
AND cast(A.TransactionDateTime as date) = cast(D.TransactionDateTime as date)
AND A.AccountNo = D.AccountNo
AND A.AccountNo = E.AccountNo
AND A.AccountNo = F.AccountNo
AND A.TransactionDateTime>D.TransactionDateTime
GROUP BY A.AccountNo,cast(A.TransactionDateTime as date),
D.AccountNo,cast(D.TransactionDateTime as date),
E.AccountNo,cast(E.TransactionDateTime as date),
F.AccountNo,cast(F.TransactionDateTime as date)
HAVING SUM(A.TransactionBaseAmount)>(SUM(D.TransactionBaseAmount)+SUM(E.TransactionBaseAmount)+SUM(F.TransactionBaseAmount))/2
对于第一个SQL,它在1分钟内完成。在最后一个SQL中,我运行它超过30分钟,并且没有得到任何结果(因为真实数据更大),我取消了它,认为失败了。
谁能帮帮我?
答案 0 :(得分:0)
您可以执行以下操作:
;with cre as (
select * from (
select *, sum(TransactionBaseAmount) over (partition by AccountNo, DCFlag) sumover
, max(TransactionDateTime)over (partition by AccountNo, DCFlag) maxdate
, row_number() over (partition by AccountNo order by TransactionDateTime desc) rn
from #t
where DCFlag = 'CREDIT'
)x
where rn = 1
),
deb as (
select AccountNo,
sum(TransactionBaseAmount) sumover
, max(TransactionDateTime) maxdate
from #t
where DCFlag = 'DEBIT'
group by AccountNo
)
select cre.AccountNo
from cre
join deb on cre.AccountNo = deb.AccountNo
where datediff(dd,cre.TransactionDateTime, deb.maxdate) <= 3 and cre.TransactionDateTime <= deb.maxdate and cre.sumover / 2 - deb.sumover >= 0
or cre.TransactionDateTime > deb.maxdate
您可以在以下位置对其进行测试: SQL FIDDLE