[英]Query Optimization Needed to Compare A/c Balances at Two Dates [ADO MS-Access Query]
我想知道兩個不同日期結束時的余額差(余額比較)。
我在MS-Access 2003版本(DATABASE VERSION Access2000)中具有以下表結構:
CreditID TxnDate PartyID TxnType金額注釋
DebitID TxnDate PartyID TxnType金額注釋
PartyID PartyName PartyAddress PartyContactNo描述
。
我使用VB6和ADO2運行下面的QUERY,以在兩個不同日期的末尾獲得“帳戶余額”,以進行比較。
。
SELECT P.PartyID, P.PartyName,
IIF((SELECT SUM(C.Amount) FROM Credits C WHERE C.PartyID = P.PartyID AND C.TxnDate <= "#31/07/2014#") IS NULL,0,(SELECT SUM(C.Amount) FROM Credits C WHERE C.PartyID = P.PartyID AND C.TxnDate <= "#31/07/2014#"))
-
IIF((SELECT SUM(D.Amount) FROM Debits D WHERE D.PartyID = P.PartyID AND D.TxnDate <= "#31/07/2014#") IS NULL, 0, (SELECT SUM(D.Amount) FROM Debits D WHERE D.PartyID = P.PartyID AND D.TxnDate <= "#31/07/2014#")) AS BalanceOn31Jul2014,
IIF((SELECT SUM(C.Amount) FROM Credits C WHERE C.PartyID = P.PartyID AND C.TxnDate <= "#31/08/2014#") IS NULL, 0, (SELECT SUM(C.Amount) FROM Credits C WHERE C.PartyID = P.PartyID AND C.TxnDate <= "#31/08/2014#"))
-
IIF((SELECT SUM(D.Amount) FROM Debits D WHERE D.PartyID = P.PartyID AND D.TxnDate <= "#31/08/2014#") IS NULL, 0, (SELECT SUM(D.Amount) FROM Debits D WHERE D.PartyID = P.PartyID AND D.TxnDate <= "#31/08/2014#")) AS BalanceOn31Aug2014
FROM Parties AS P
ORDER BY PartyName;
上面的查詢運行,但是非常慢。
我想知道是否仍然可以優化上述“ QUERY”?
我認為使用group by
一次性計算所有貸方和借方會更快:
select
c.PartyID,
c.PartyName,
Nz(c.Credit31Jul2014, 0) - Nz(d.Debit31Jul2014, 0) as BalanceOn31Jul2014,
Nz(c.Credit31Aug2014, 0) - Nz(d.Debit31Aug2014, 0) as BalanceOn31Aug2014
from (
select
p.PartyID,
p.PartyName,
sum(iif(c.TxnDate <= #31/07/2014#, c.amount, 0)) as Credit31Jul2014,
sum(iif(c.TxnDate <= #31/08/2014#, c.amount, 0)) as Credit31Aug2014
from
Parties p
left outer join
Credits c
on p.PartyID = c.PartyID
group by
p.PartyID,
p.PartyName
) c left outer join (
select
d.PartyID,
sum(iif(d.TxnDate <= #31/07/2014#, d.amount, 0)) as Debit31Jul2014,
sum(iif(d.TxnDate <= #31/08/2014#, d.amount, 0)) as Debit31Aug2014
from
Debits d
where
d.TxnDate <= #31/08/2014#
group by
d.PartyID
) d on c.PartyID = d.PartyID
order by
c.PartyName;
您可能需要考慮存儲一個余額表,該表可以在各個日期(例如每月一次)保持聚會余額。 那將限制您必須求和的時間間隔。
看看為什么快。 首先,對於您的查詢,您基本上在運行至少4個,每個PartyID可能有8個選擇。 您可以使用Nz(sum(xxx), 0)
而不是Iif(sum(xxx) is null, 0, sum(xxx))
稍微簡化Iif(sum(xxx) is null, 0, sum(xxx))
。 這樣只能保證4。這些選擇中的每一個都需要讀取整個貸方或借方表。 現在,單獨考慮查詢的這一部分:
select
d.PartyID,
sum(iif(d.TxnDate <= #31/07/2014#, d.amount, 0)) as Debit31Jul2014,
sum(iif(d.TxnDate <= #31/08/2014#, d.amount, 0)) as Debit31Aug2014
from
Debits d
where
d.TxnDate <= #31/08/2014#
group by
d.PartyID
這將獲得每一方的總借方。 想象得到一個分類帳並被要求進行計算。 您將使用筆記本來保留部分結果。 如果每個分類帳項目都符合您在記事本中查找的日期標准,以查看您是否有此聚會的記錄,則您將依次閱讀。 如果沒有,您將在行中添加一個。 如果您這樣做,則將金額替換為金額加上該行中的金額。 要意識到的關鍵是,您只需閱讀一次分類帳就可以完成所有這些工作。 使用您的方法,您每方要多次讀取分類帳。
我在代碼的第4行和第5行中修改了Laurence對AVOID Nz / IIf的回答。
感謝Laurance,沒有他,我現在無法回答這個問題。
因此,我使用的最終代碼是
SELECT cc.PartyID, cc.PartyName,
(cc.Credit31Jul2014 - dd.Debit31Jul2014) AS BalanceOn31Jul2014,
(cc.Credit31Aug2014 - dd.Debit31Aug2014) AS BalanceOn31Aug2014
FROM
(SELECT p.PartyID, p.PartyName,
SUM(IIF(c.TxnDate <= #31/07/2014#, c.amount, 0)) AS Credit31Jul2014,
SUM(IIF(c.TxnDate <= #31/08/2014#, c.amount, 0)) AS Credit31Aug2014
FROM Parties p
LEFT OUTER JOIN Credits c ON p.PartyID = c.PartyID
GROUP BY p.PartyID, p.PartyName) AS cc
LEFT OUTER JOIN
(SELECT p.PartyID,
SUM(IIF(d.TxnDate <= #31/07/2014#, d.amount, 0)) AS Debit31Jul2014,
SUM(IIF(d.TxnDate <= #31/08/2014#, d.amount, 0)) AS Debit31Aug2014
FROM Parties p
LEFT OUTER JOIN Debits d ON p.PartyID = d.PartyID
GROUP BY p.PartyID) AS dd
ON dd.PartyID = cc.PartyID
ORDER BY cc.PartyName;
。 感謝Laurence @Laurence
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.