2011-10-17 39 views
0

我試圖產生debitors的年齡平衡,但我使用MySQL SUM時,我必須採取平衡考慮在內有touble。Mysql的SUM - 如何避免和同樣的東西多次

我可以得到客戶的當前餘額:

SELECT SUM(balance) FROM `transaction` WHERE customer_id = 1 

起初,當我希望得到一箇舊的平衡 - 即。平衡的樣子2011-08-31我認爲以下是不夠的:

SELECT SUM(balance) FROM `transaction` WHERE customer_id = 1 AND posted <= '2011-08-31' 

但上面並沒有採取自2011-09-01已發生到現在考慮任何平衡的歷史。我已經儲存了所有歷史的平衡在一個表中。所以,如果一個客戶(部分)埋單2011-09-06那麼表將類似於以下內容:

交易:

id | text | amount | balance | posted 
1 | Invoice | 100.00 | 20.00 | 2011-08-14 
2 | Payment | 80.00 | 0.00 | 2011-09-06 

平衡歷史:

id | source | destination | amount | created 
1 |  1 |   2 | 80.00 | 2011-09-06 

我想我用下面的查詢解決它:

SELECT customer_id, SUM(balance)+SUM(IFNULL(bh_source.amount, 0))-SUM(IFNULL(bh_destination.amount, 0)) AS `current_balance` 
FROM `transaction` 
LEFT JOIN balancehistory AS bh_source ON `transaction`.id = bh_source.source AND DATE(bh_source.created) > "2011-08-31" 
LEFT JOIN balancehistory AS bh_destination ON `transaction`.id = bh_destination.destination AND DATE(bh_destination.created) > "2011-08-31" 
WHERE posted <= "2011-08-31" 
GROUP BY customer_id 

但當平衡歷史BECO mes更復雜,即。像下面 - 它失敗:

交易:

id | text    | amount | balance | posted 
1 | Invoice   | 100.00 | 0.00 | 2011-08-14 
2 | Payment   | -80.00 | 0.00 | 2011-09-06 
3 | Payment cancelled | 80.00 | 0.00 | 2011-09-08 
4 | VISA    | -100.00 | 0.00 | 2011-10-10 

平衡歷史:

id | source | destination | amount | created 
1 |  1 |   2 | 80.00 | 2011-09-06 
2 |  2 |   1 | -80.00 | 2011-09-08 
3 |  3 |   2 | 80.00 | 2011-09-08 
4 |  1 |   4 | -100.00 | 2011-10-10 

我一直在敲打我的頭靠在牆上,現在很長一段時間,希望你們有一些建議。表結構鎖定,如果需要的話也可以改變。

謝謝。

更新:

現在我看到,我已經簡化我的問題太多 - 但無論如何感謝湯姆。 我不(僅)感興趣的當前總,而是我要根據他們的到期日金額羣。我試圖創建一個表,該表顯示多少了,由於付款。 IE瀏覽器。 0-30之間的天,30-90天等。:

年齡平衡(多個SQL使用以下數據不同的基準日期的結果):

reference | before due | 0-30 days | 30-90 days 
2011-08-31 |  233.79 |  0.00 |  0.00 
2011-09-02 |  0.00 |  0.00 |  0.00 
2011-09-07 |  0.00 | 233.79 |  0.00 
2011-10-18 |  100.00 |  0.00 |  233.79 
2011-10-25 |  0.00 | 100.00 |  233.79 
2011-10-28 |  0.00 |  0.00 |  0.00 

交易:

id | customer_id | text    | amount | balance | posted  | due 
1 |   1 | Invoice 1  | 233.79 | 0.00 | 2011-08-17 | 2011-09-01 
2 |   1 | Payment 1  | -233.79 | 0.00 | 2011-09-01 | 2011-09-01 
3 |   1 | Payment rejected | 233.79 | 0.00 | 2011-09-06 | 2011-09-06 
4 |   1 | Reminder   | 100.00 | 0.00 | 2011-09-14 | 2011-09-23 
5 |   1 | Payment 2  | -333.79 | 0.00 | 2011-09-23 | 2011-09-23 

餘額歷史:

id | source | destination | amount | created 
1 |  1 |   2 | 233.79 | 2011-09-05 
2 |  2 |   1 | 233.79 | 2011-09-09 
3 |  3 |   2 | 233.79 | 2011-09-09 
4 |  1 |   5 | 233.79 | 2011-10-26 
5 |  4 |   5 | 100.00 | 2011-10-26 

下面是一個我認爲SQL的示例會查找特定日期的年齡平衡:

SELECT SUM(IF("2011-08-31" <= due, balance, 0)) 
    + SUM(IF("2011-08-31" <= due, IFNULL(bh_source.amount, 0), 0)) 
    - SUM(IF("2011-08-31" <= due, IFNULL(bh_destination.amount, 0), 0)) AS before_due, 
     SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 0 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 30 DAY)), balance, 0)) 
    + SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 0 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 30 DAY)), IFNULL(bh_source.amount, 0), 0)) 
    - SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 0 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 30 DAY)), IFNULL(bh_destination.amount, 0), 0)) AS 0_30_days, 
     SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 30 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 90 DAY)), balance, 0)) 
    + SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 30 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 90 DAY)), IFNULL(bh_source.amount, 0), 0)) 
    - SUM(IF("2011-08-31" > DATE(ADDDATE(due, INTERVAL 30 DAY)) AND 
       "2011-08-31" <= DATE(ADDDATE(due, INTERVAL 90 DAY)), IFNULL(bh_destination.amount, 0), 0)) AS 30_90_days 
FROM `transaction` 
LEFT JOIN balancehistory AS bh_source ON `transaction`.id = bh_source.source AND DATE(bh_source.created) > "2011-08-31" 
LEFT JOIN balancehistory AS bh_destination ON `transaction`.id = bh_destination.destination AND DATE(bh_destination.created) > "2011-08-31" 
WHERE posted <= "2011-08-31" 
GROUP BY customer_id 

但它不能按預期工作。任何幫助/建議,將不勝感激。

回答

0

如果將發票和支付交易分成兩個單獨的表格,您可能會有更多樂趣。例如:

invoice 
id | customer_id | invoice_description | amount | postedOn 
1 |  1  | Services Invoice  | 100.00 | 2011-08-14 12:35:01 

payment 
id | customer_id | invoice_id | payment_type  | amount | madeOn 
1 |  1  |  1  | Payment    | -80.00 | 2011-09-08 08:09:12 
1 |  1  |  1  | Payment Cancelled | 80.00 | 2011-09-08 08:12:34 
1 |  1  |  1  | VISA Payment  | -100.00 | 2011-10-10 17:22:54 

那麼你應該能夠在任何時候獲得及時爲特定客戶的當前餘額通過獲取及時發給他們到這一點,所有發票之和減去收到的付款在相同的發票時間點之前。因此:

select customer_id,sum(invoice_balance) as totalBalance 
from 
(
select i.customer_id, i.id as invoice_id, 
i.amount - sum(ifnull(p.amount,0)) as invoice_balance 
from invoice i 
left join (select p.invoice_id,p.amount from payment where p.madeOn > '2011-09-01') p 
on p.invoice_id = i.id 
where i.postedOn > '2011-09-01' 
group by i.customer_id, i.id, i.amount 
) t group by customer_id; 

我已經省略CUSTOMER_ID聯接的目的,因爲我想這是可能的(但不太可能)由不同的客戶爲之發票在最初發布的客戶進行支付。進一步考慮它可能需要將支付表上的payment_type列標準化爲paymentType表或類似的東西。

+0

根據我最初的問題,你的回答是正確的,但我意識到我的問題是錯誤的:-S – Jacob