У меня есть таблица Operation
, которая содержит 5 столбцов:
- id
- bankAccount_id
- valueDate
- дебет (всегда положительный)
- кредит
- остаток
Я хочу обновить баланс всех операций банковского счета.
Я закончил с этим SQL запрос после прочтения некоторых вопросов и ответов SO:
UPDATE Operation INNER JOIN (
SELECT
id,
credit,
debit,
@Balance := @Balance + IFNULL(credit,0) - IFNULL(debit,0) AS Balance
FROM Operation, (SELECT @Balance := 0) AS variableInit
WHERE bankAccount_id = 1
ORDER BY valueDate ASC, id ASC
) subRequest ON Operation.id = subRequest.id
SET Operation.balance = subRequest.Balance;
Хорошо работает, когда значения valueDates операций находятся в том же порядке, что и идентификаторы. Но когда сначала выполняются операции с большими идентификаторами, это не работает.
Как видно, операция 22 является последней обновленной, несмотря на то, что это первая операция, упорядоченная по дате валютирования!
+----+---------------------+--------+---------+---------+
| id | valueDate | debit | credit | balance |
+----+---------------------+--------+---------+---------+
| 22 | 2018-01-01 00:00:00 | NULL | 103.00 | 618.00 |
| 1 | 2020-01-15 14:00:00 | NULL | 1000.00 | 1000.00 |
| 2 | 2020-01-15 15:00:00 | NULL | 200.00 | 1200.00 |
| 3 | 2020-01-15 16:00:00 | 50.00 | NULL | 1150.00 |
| 4 | 2020-01-18 17:00:00 | 200.00 | NULL | 950.00 |
| 5 | 2020-01-19 18:00:00 | NULL | 20.00 | 970.00 |
| 6 | 2020-01-21 20:00:00 | 500.00 | NULL | 470.00 |
| 7 | 2020-01-21 20:00:00 | 10.00 | NULL | 460.00 |
| 8 | 2020-01-21 20:00:00 | NULL | 30.00 | 490.00 |
| 9 | 2020-02-02 01:00:00 | 5.00 | NULL | 485.00 |
| 10 | 2020-02-10 09:00:00 | 10.00 | NULL | 475.00 |
| 11 | 2020-02-11 10:00:00 | NULL | 40.00 | 515.00 |
+----+---------------------+--------+---------+---------+
Что я не понимаю, так это то, что когда я запускаю только один внутренний запрос, он возвращает операции с правильным порядком и правильным балансом !
Что я могу сделать, чтобы сделать мой запрос на обновление работает?
Вот структура данных, которую вы можете использовать для тестирования:
CREATE TABLE `Operation` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`valueDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`debit` decimal(10,2) DEFAULT NULL,
`credit` decimal(10,2) DEFAULT NULL,
`balance` decimal(10,2) NOT NULL,
`bankAccount_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Operation` VALUES (1,'2020-01-15 13:00:00',NULL,1000.00,0.00,1),(2,'2020-01-15 14:00:00',NULL,200.00,0.00,1),(3,'2020-01-15 15:00:00',50.00,NULL,0.00,1),(4,'2020-01-18 16:00:00',200.00,NULL,0.00,1),(5,'2020-01-19 17:00:00',NULL,20.00,0.00,1),(6,'2020-01-21 19:00:00',500.00,NULL,0.00,1),(7,'2020-01-21 19:00:00',10.00,NULL,0.00,1),(8,'2020-01-21 19:00:00',NULL,30.00,0.00,1),(9,'2020-02-02 00:00:00',5.00,NULL,0.00,1),(10,'2020-02-10 08:00:00',10.00,NULL,0.00,1),(11,'2020-02-11 09:00:00',NULL,40.00,0.00,1),(12,'2020-01-21 19:00:00',NULL,500.00,0.00,2),(13,'2020-01-22 20:00:00',NULL,15.00,0.00,2),(14,'2020-02-02 00:00:00',NULL,5.00,0.00,2),(15,'2020-02-05 03:00:00',30.00,NULL,0.00,2),(16,'2020-02-10 08:00:00',NULL,60.00,0.00,2),(17,'2019-12-30 22:00:00',NULL,50.00,0.00,3),(18,'2020-01-21 19:00:00',10.00,NULL,0.00,3),(19,'2020-01-21 19:00:00',30.00,NULL,0.00,3),(20,'2020-01-21 19:00:00',100.00,NULL,0.00,3),(21,'2020-01-27 22:00:00',NULL,55.00,0.00,3),(22,'2017-12-31 23:00:00',NULL,103.00,0.00,1);
И вы можете заказать операции с:
select * from Operation where bankAccount_id = 1 ORDER BY valueDate ASC, id ASC;