2014-11-25 95 views
2

我有以下表格是BankDetails和Transactiondetails。使用这两个表格,我想获取帐户名称的当前余额。优化SQL查询以计算帐户余额

表:

Create table Bankdetails 
(
AccName varchar(50), 
AccNo int, 
OpBal numeric(18,2) 
) 

Create table Trandetails 
(
AccNo int, 
Amount numeric(18,2), 
Trantype varchar(10) 
) 

两个表插入脚本:

insert into Bankdetails values('A', 12345, 30000.00) 
insert into Bankdetails values('B', 13345, 30000.00) 
insert into Bankdetails values('C', 14545, 30000.00) 
insert into Bankdetails values('D', 15045, 30000.00) 

insert into Trandetails values(12345, 5000.00, 'Credit') 
insert into Trandetails values(13345, 5000.00, 'Debit') 
insert into Trandetails values(15045, 5000.00, 'Debit') 
insert into Trandetails values(13345, 5000.00, 'Credit') 
insert into Trandetails values(12345, 5000.00, 'Debit') 
insert into Trandetails values(13345, 5000.00, 'Debit') 
insert into Trandetails values(14545, 5000.00, 'Credit') 
insert into Trandetails values(15045, 5000.00, 'Debit') 
insert into Trandetails values(14545, 5000.00, 'Debit') 

输出会是这样的:

AccName Accno CurrBal 
    A  12345 30000.00 
    B  13345 25000.00 
    C  14545 30000.00 
    D  15045 20000.00 

我需要帐户Holdername,帐号和当前余额使用以上两张表。

以下是我的查询,我希望得到优化的查询,即不使用子查询,如果可能的话。 注意:在我的情况下,信用=增加到账户和借方=金额从账户中扣除。

Select bd.accname, bd.accno, 
(bd.opbal - isnull((select SUM(Amount) from Trandetails where Trantype = 'Debit' and accno = bd.accno group by accno),0) + isnull((select SUM(Amount) from Trandetails where Trantype = 'Credit' and accno = bd.accno group by accno),0)) as Bal 
From Bankdetails BD inner join Trandetails TD on td.AccNo = bd.AccNo 
group by bd.accno, bd.accname, bd.opbal 

对于不遵循表的正确命名约定,我深表歉意。任何帮助将不胜感激。

谢谢,

帕雷什Ĵ

+0

我通常建议,而不是一个'TranType'立柱稍稍让'Amount'列包含正反两方面的值,并使用一个约定(如正面是信用卡,负是借)。它使得大多数有用的查询更容易。否则,就目前的设计而言,您可能会错过'CHECK'约束来阻止* Amount发生负面影响 - 除非您希望申请负面信用的人员? – 2014-11-25 07:21:23

+0

@Damien_The_Unbeliever:TranType保持捕捉交易类型。在实际的表格中,它包含比CREDIT&Debit更多的细节。因此不能从表中删除这些列。 – 2014-11-25 07:25:50

+0

@Damien_The_Unbeliever:可能有其他优化解决方案吗?我的意思不是很复杂的查询。 – 2014-11-25 07:27:28

回答

3

的想法是第一以生成针对每个事务类型,DebitCredit总和。然后,将其加入Bankdetails以计算当前余额。

;with cte as(
    select 
     AccNo, 
     Credit = sum(case when TranType = 'Credit' then Amount else 0 end), 
     Debit = sum(case when TranType = 'Debit' then Amount else 0 end) 
    from Trandetails 
    group by 
     AccNo 
) 
select 
    bd.AccName, 
    bd.AccNo, 
    CurrBal = bd.opBal - c.Debit + c.Credit 
from BankDetails bd 
inner join cte c 
    on c.Accno = bd.Accno 
-1
SELECT 
    Bankdetails.AccName 
    , Bankdetails.AccNo 
    , Bankdetails.OpBal 
     + SUM(CASE WHEN TranType = 'Credit' THEN Amount ELSE 0 END) 
     - SUM(CASE WHEN TranType = 'Debit' THEN Amount ELSE 0 END) 
    AS 'CurrBal' 
FROM Trandetails 
    INNER JOIN Bankdetails ON Bankdetails.AccNo = Trandetails.AccNo 
GROUP BY Bankdetails.AccNo, Bankdetails.AccName 
+0

如果你能解释你的代码,那将会很棒。这将有助于OP以及其他SO用户。 :) – jazzurro 2014-11-25 07:02:37

+0

有上述解决方案的错误夫妇。 1.不明确的列名称'AccNo'。 2.由于您未在GROUP BY – 2014-11-25 07:03:04

+0

中包含其他列名称,因此Group'by Bankdetails.AccName'中的'Bankdetails.AccName'仍然缺少'Bankdetails.OpBal' – bummi 2014-11-26 07:11:42