满足指定时间内指定要求的项目

时间:2015-12-23 07:17:02

标签: sql-server

朋友:

我对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分钟,并且没有得到任何结果(因为真实数据更大),我取消了它,认为失败了。

谁能帮帮我?

1 个答案:

答案 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