我正在试图弄清楚如何将现金从一个帐户推入/拉入其他帐户并按帐户跟踪余额。我能想到解释这个问题的最佳模式是"小额现金"。有一个主要的小额现金"有现金的账户,然后其他账户提取现金并将现金返还(以FIFO方式)。处理完所有交易后,我想知道已经将多少小额现金转移到其他每个账户。
功能
示例数据设置
CREATE TABLE IF NOT EXISTS transactions (
id serial PRIMARY KEY, account_id int, date DATE, amount int);
INSERT INTO transactions (account_id, date, amount) VALUES
/* Petty cash account transaction;
all other accounts will pull from this cash */
(1, '2017-01-01', 5),
/* Other account transactions that will
pull from petty cash */
(2, '2017-01-02', -2),
(3, '2017-01-03', -8),
(4, '2017-01-04', -6),
(3, '2017-01-05', 10),
(2, '2017-01-06', 1);
预期输出
| account_id | cash_balance | notes |
|------------|--------------|----------------------------------------------------|
| 1 | 0 | Petty cash account depleted |
| 2 | 1 | Total spending was -1 |
| 3 | 0 | Total spending was +2, we gave all petty cash back |
| 4 | 4 | Total spending was -6, we had 4 left to pull |
答案 0 :(得分:0)
我终于想出办法来做到这一点。使用两步流程,我首先计算每个帐户交易的“调整金额”,这减少了同一帐户FIFO上任何可用退款的支出。然后,在步骤2中,我使用这些调整后的金额FIFO从小额现金“拉”。
CREATE TABLE IF NOT EXISTS transactions (
id serial PRIMARY KEY, account_id int, date DATE, amount int);
INSERT INTO transactions (account_id, date, amount) VALUES
/* Petty cash account transaction;
all other accounts will pull from this cash */
(1, '2017-01-01', 5),
/* Other account transactions that will
pull from petty cash */
(2, '2017-01-02', -2),
(3, '2017-01-03', -8),
(4, '2017-01-04', -6),
(3, '2017-01-05', 10),
(2, '2017-01-06', 1);
WITH e_adjusted_amounts AS (
SELECT id, account_id, amount,
/* adjusted_amount: the amount adjusted for returns, FIFO.
This gives us a logical amount for outflows, adjusted for corresponding inflows
that can be used later when we start pulling from petty cash. */
amount - LEAST(0, GREATEST(amount,
-( -- total of all preceeding outflows
COALESCE((SUM(amount) FILTER (WHERE amount < 0) OVER (PARTITION BY account_id ORDER BY id)) - amount,0)
-- total of all inflows
+ COALESCE(SUM(amount) FILTER (WHERE amount > 0) OVER (PARTITION BY account_id),0)
)
)
) as adjusted_amount
FROM transactions
),
e_pull_amounts AS (
SELECT a.id, a.account_id, a.amount, a.adjusted_amount, LEAST(0, GREATEST(a.adjusted_amount,
-( petty_cash.amount
-- total of all preceeding outflows
+ COALESCE((SUM(a.adjusted_amount) OVER (ORDER BY id)) - a.adjusted_amount,0)
)
)
) as pull_amount
FROM e_adjusted_amounts a,
(SELECT amount FROM transactions WHERE account_id = 1) petty_cash
-- Outflows only
WHERE adjusted_amount < 0
AND account_id != 1
)
SELECT account_id, SUM(pull_amount) as cash_balance
FROM e_pull_amounts
GROUP BY account_id
ORDER BY account_id;