Я пытаюсь сгенерировать возрастной баланс дебиторов, но у меня возникает двойное использование 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
Но когда история балансировки становится более сложной, т.е.как следующее - это не удается:
Транзакции:
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
Я долго бился головой о стенуНадеюсь, у вас есть предложения.Структура таблицы не заблокирована, поэтому при необходимости ее можно изменить.
Спасибо.
Обновление:
Теперь я вижу, что слишком сильно упростил свою проблему - но все равно спасибо, Том.Меня (только) не интересует текущая сумма, но вместо этого я хочу сгруппировать суммы на основе их срока оплаты.Я пытаюсь создать таблицу, которая показывает, сколько просроченных платежей.То есть.от 0 до 30 дней, 30-90 дней и т. д.:
1039 * Баланс по возрасту (несколько результатов SQL с использованием различных контрольных дат для следующих данных):
* Транзакции:
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
Но это не такработать как задумано.Любая помощь / предложения будут оценены.