web-dev-qa-db-ja.com

口座番号に基づいてランニング残高列を作成するにはどうすればよいですか?

1つまたは複数のアカウントのアカウントステートメントを返すストアドプロシージャがあります。ここで問題があるのは、アカウント番号に基づいて各レコードの実行残高を返すことです。クエリで各アカウントの残高がリセットされません。これを行うにはどうすればよいですか?

  SELECT 
    acc_account_transactions.account_no,
      COALESCE(debit_balance) as debits
     , COALESCE(credit_balance) as  credits
     , (@running_balance := @running_balance + (acc_account_transactions.debit_balance - acc_account_transactions.credit_balance)) as balance
  FROM acc_account_transactions
  JOIN (SELECT @running_balance := 0) r
  ORDER BY account_no

これを実行すると、次のようになりますが、アカウントごとに残高がリセットされません

account  debit           credit             balance
13  |2578.19        | 0.00      |  2578.19
13  |1500.00        | 0.00      |  4078.19
13  |1500000.00     | 0.00      |  1504078.19
13  |1500.00        | 0.00      |  1505578.19
14  |1500000.00     | 0.00      |  3005578.19  <--- reset before this
14  |0.00           | 13500.00  |  2992078.19
14  |0.00           | 13500.00  |  2978578.19
14  |33458.43       | 0.00      |  3012036.62
15  |0.00           | 100000.00 |  2912036.62  <--- reset before this
15  |18506.34       | 0.00      |  2930542.96
16  |946.20         | 0.00      |  2931489.16  <--- reset before this
17  |90364.77       | 0.00      |  3021853.93  <--- reset before this
21  |0.00           | 0.00      |  3021853.93  <--- reset before this
22  |0.00           | 0.00      |  3021853.93  <--- reset before this
23  |0.00           | 0.00      |  3021853.93  <--- reset before this
23  |1105500.00     | 0.00      |  4127353.93
24  |1327.00        | 0.00      |  4128680.93  <--- reset before this
25  |0.00           | 0.00      |  4128680.93  <--- reset before this

ありがとう

1
Abeer Sul

簡単に必要なようです

SELECT *, SUM(debit_balance - credit_balance)
             OVER (PARTITION BY account_no ORDER BY id) balance
FROM acc_account_transactions

フィドル

3
Akina

クエリにリセットする機能がありませんでした@running_balance。リセットできるのは@running_balance行が異なる場合account_no前の行から。

これを念頭に置いて、( ドラムロールください )...

提案されたクエリ

SELECT account_no,debits,credits,balance FROM
(SELECT 
   account_no
  ,COALESCE(debit_balance)  as debits
  ,COALESCE(credit_balance) as credits
  ,(@running_balance := IF(@curr_account_no < account_no,         0,@running_balance)) prev_runnng_bal
  ,(@curr_account_no := IF(@curr_account_no < account_no,account_no,@curr_account_no)) curr_account_no
  ,(@running_balance := @running_balance + (acc_account_transactions.debit_balance - acc_account_transactions.credit_balance)) as balance
FROM acc_account_transactions,(SELECT @running_balance := 0,@curr_account_no := 0) r
ORDER BY account_no) A;

提案されたクエリ内のサブクエリ

SELECT 
   account_no
  ,COALESCE(debit_balance)  as debits
  ,COALESCE(credit_balance) as credits
  ,(@running_balance := IF(@curr_account_no < account_no,         0,@running_balance)) prev_runnng_bal
  ,(@curr_account_no := IF(@curr_account_no < account_no,account_no,@curr_account_no)) curr_account_no
  ,(@running_balance := @running_balance + (acc_account_transactions.debit_balance - acc_account_transactions.credit_balance)) as balance
FROM acc_account_transactions,
     (SELECT @running_balance := 0,@curr_account_no := 0) r
ORDER BY account_no;

サンプルデータ

DROP DATABASE IF EXISTS abeersul;
CREATE DATABASE abeersul;
USE abeersul
CREATE TABLE acc_account_transactions
(
    id             INT NOT NULL AUTO_INCREMENT,
    account_no     INT NOT NULL,
    debit_balance  DOUBLE NOT NULL,
    credit_balance DOUBLE NOT NULL,
    PRIMARY KEY (id)
);
INSERT INTO acc_account_transactions
(account_no,debit_balance,credit_balance) VALUES
(13,2578.19        , 0.00     ),
(13,1500.00        , 0.00     ),
(13,1500000.00     , 0.00     ),
(13,1500.00        , 0.00     ),
(14,1500000.00     , 0.00     ),
(14,0.00           , 13500.00 ),
(14,0.00           , 13500.00 ),
(14,33458.43       , 0.00     ),
(15,0.00           , 100000.00),
(15,18506.34       , 0.00     ),
(16,946.20         , 0.00     ),
(17,90364.77       , 0.00     ),
(21,0.00           , 0.00     ),
(22,0.00           , 0.00     ),
(23,0.00           , 0.00     ),
(23,1105500.00     , 0.00     ),
(24,1327.00        , 0.00     ),
(25,0.00           , 0.00     );
SELECT * FROM acc_account_transactions;

ロードされたサンプルデータ

mysql> DROP DATABASE IF EXISTS abeersul;
Query OK, 1 row affected (0.02 sec)

mysql> CREATE DATABASE abeersul;
Query OK, 1 row affected (0.00 sec)

mysql> USE abeersul
Database changed
mysql> CREATE TABLE acc_account_transactions
    -> (
    ->     id             INT NOT NULL AUTO_INCREMENT,
    ->     account_no     INT NOT NULL,
    ->     debit_balance  DOUBLE NOT NULL,
    ->     credit_balance DOUBLE NOT NULL,
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO acc_account_transactions
    -> (account_no,debit_balance,credit_balance) VALUES
    -> (13,2578.19        , 0.00     ),
    -> (13,1500.00        , 0.00     ),
    -> (13,1500000.00     , 0.00     ),
    -> (13,1500.00        , 0.00     ),
    -> (14,1500000.00     , 0.00     ),
    -> (14,0.00           , 13500.00 ),
    -> (14,0.00           , 13500.00 ),
    -> (14,33458.43       , 0.00     ),
    -> (15,0.00           , 100000.00),
    -> (15,18506.34       , 0.00     ),
    -> (16,946.20         , 0.00     ),
    -> (17,90364.77       , 0.00     ),
    -> (21,0.00           , 0.00     ),
    -> (22,0.00           , 0.00     ),
    -> (23,0.00           , 0.00     ),
    -> (23,1105500.00     , 0.00     ),
    -> (24,1327.00        , 0.00     ),
    -> (25,0.00           , 0.00     );
Query OK, 18 rows affected (0.00 sec)
Records: 18  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM acc_account_transactions;
+----+------------+---------------+----------------+
| id | account_no | debit_balance | credit_balance |
+----+------------+---------------+----------------+
|  1 |         13 |       2578.19 |              0 |
|  2 |         13 |          1500 |              0 |
|  3 |         13 |       1500000 |              0 |
|  4 |         13 |          1500 |              0 |
|  5 |         14 |       1500000 |              0 |
|  6 |         14 |             0 |          13500 |
|  7 |         14 |             0 |          13500 |
|  8 |         14 |      33458.43 |              0 |
|  9 |         15 |             0 |         100000 |
| 10 |         15 |      18506.34 |              0 |
| 11 |         16 |         946.2 |              0 |
| 12 |         17 |      90364.77 |              0 |
| 13 |         21 |             0 |              0 |
| 14 |         22 |             0 |              0 |
| 15 |         23 |             0 |              0 |
| 16 |         23 |       1105500 |              0 |
| 17 |         24 |          1327 |              0 |
| 18 |         25 |             0 |              0 |
+----+------------+---------------+----------------+
18 rows in set (0.00 sec)

mysql>

提案されたクエリ内でサブクエリが実行されました

mysql> SELECT
    ->    account_no
    ->   ,COALESCE(debit_balance)  as debits
    ->   ,COALESCE(credit_balance) as credits
    ->   ,(@running_balance := IF(@curr_account_no < account_no,         0,@running_balance)) prev_runnng_bal
    ->   ,(@curr_account_no := IF(@curr_account_no < account_no,account_no,@curr_account_no)) curr_account_no
    ->   ,(@running_balance := @running_balance + (acc_account_transactions.debit_balance - acc_account_transactions.credit_balance)) as balance
    -> FROM acc_account_transactions,
    ->      (SELECT @running_balance := 0,@curr_account_no := 0) r
    -> ORDER BY account_no;
+------------+----------+---------+-----------------+-----------------+------------+
| account_no | debits   | credits | prev_runnng_bal | curr_account_no | balance    |
+------------+----------+---------+-----------------+-----------------+------------+
|         13 |     1500 |       0 | 0               | 13              |       1500 |
|         13 |  1500000 |       0 | 1500            | 13              |    1501500 |
|         13 |     1500 |       0 | 1501500         | 13              |    1503000 |
|         13 |  2578.19 |       0 | 1503000         | 13              | 1505578.19 |
|         14 |  1500000 |       0 | 0               | 14              |    1500000 |
|         14 |        0 |   13500 | 1500000         | 14              |    1486500 |
|         14 |        0 |   13500 | 1486500         | 14              |    1473000 |
|         14 | 33458.43 |       0 | 1473000         | 14              | 1506458.43 |
|         15 | 18506.34 |       0 | 0               | 15              |   18506.34 |
|         15 |        0 |  100000 | 18506.34        | 15              |  -81493.66 |
|         16 |    946.2 |       0 | 0               | 16              |      946.2 |
|         17 | 90364.77 |       0 | 0               | 17              |   90364.77 |
|         21 |        0 |       0 | 0               | 21              |          0 |
|         22 |        0 |       0 | 0               | 22              |          0 |
|         23 |        0 |       0 | 0               | 23              |          0 |
|         23 |  1105500 |       0 | 0               | 23              |    1105500 |
|         24 |     1327 |       0 | 0               | 24              |       1327 |
|         25 |        0 |       0 | 0               | 25              |          0 |
+------------+----------+---------+-----------------+-----------------+------------+
18 rows in set (0.00 sec)

mysql>

提案されたクエリが実行されました

mysql> SELECT account_no,debits,credits,balance FROM
    -> (SELECT
    ->    account_no
    ->   ,COALESCE(debit_balance)  as debits
    ->   ,COALESCE(credit_balance) as credits
    ->   ,(@running_balance := IF(@curr_account_no < account_no,         0,@running_balance)) prev_runnng_bal
    ->   ,(@curr_account_no := IF(@curr_account_no < account_no,account_no,@curr_account_no)) curr_account_no
    ->   ,(@running_balance := @running_balance + (acc_account_transactions.debit_balance - acc_account_transactions.credit_balance)) as balance
    -> FROM acc_account_transactions,(SELECT @running_balance := 0,@curr_account_no := 0) r
    -> ORDER BY account_no) A;
+------------+----------+---------+------------+
| account_no | debits   | credits | balance    |
+------------+----------+---------+------------+
|         13 |     1500 |       0 |       1500 |
|         13 |  1500000 |       0 |    1501500 |
|         13 |     1500 |       0 |    1503000 |
|         13 |  2578.19 |       0 | 1505578.19 |
|         14 |  1500000 |       0 |    1500000 |
|         14 |        0 |   13500 |    1486500 |
|         14 |        0 |   13500 |    1473000 |
|         14 | 33458.43 |       0 | 1506458.43 |
|         15 | 18506.34 |       0 |   18506.34 |
|         15 |        0 |  100000 |  -81493.66 |
|         16 |    946.2 |       0 |      946.2 |
|         17 | 90364.77 |       0 |   90364.77 |
|         21 |        0 |       0 |          0 |
|         22 |        0 |       0 |          0 |
|         23 |        0 |       0 |          0 |
|         23 |  1105500 |       0 |    1105500 |
|         24 |     1327 |       0 |       1327 |
|         25 |        0 |       0 |          0 |
+------------+----------+---------+------------+
18 rows in set (0.01 sec)

mysql>

試してみる !!!

1
RolandoMySQLDBA