会计余额。分层余额和汇总
Accounting Balances. Hierarchial Balances and Rollup
帐户(link 到其父帐户的主帐户列表(相同 table))
(帐户 table 使用 nested_set 插件维护,因此左、右、深度在 table 中可用,并在 adding/editing 帐户中维护)
| id | name | parent_id |
|----|----------------|-----------|
| 1 | Assets | null |
| 2 | Current Assets | 1 |
| 3 | Fixed Assets | 1 |
| 4 | Bank | 2 |
| 5 | Bank One | 4 |
| 6 | Bank Two | 4 |
| 7 | Revenue | null |
| 8 | Sales | 7 |
| 9 | Expenses | null |
| 10 | Rent | 9 |
条目(存储每笔交易的日期和描述)
| entry_id | date | description |
|----------|------------|--------------------|
| 1 | Mar 3 2020 | Cash Sales |
| 2 | Mar 3 2020 | Cash Paid For Rent |
| 3 | Apr 1 2020 | Owner Withdrawal |
金额(存储复式记账交易的地方)
| entry_id | account_id | type | amount |
|----------|------------|--------|--------|
| 1 | 5 | debit | 10000 |
| 1 | 8 | credit | 10000 |
| 2 | 10 | debit | 1000 |
| 2 | 5 | credit | 1000 |
| | | | |
鉴于上述结构,这是我的要求
- 以树状(分层)结构排列账户并计算个人账户余额(余额可以是debit_balance或credit_balance)
- 分层账户余额,将子余额汇总到父账户
PS:
我确实有上面的 req 1 的解决方案,使用的组合
WITH RECURSIVE sql 函数在账户 table 上分层排列行,然后将结果集与金额 table 相加,金额列(按类型分组后)为每个账户求和.
我很想看看这里的人将如何解决这个问题。 (让我知道你是否想看看到目前为止我得到了什么)
这是为我提供第一个结果集的查询。 (为了简洁起见,我在原始问题中省略了 normal_credit_blance 标志等细节)
select id, parent_id, name, newdepth as depth, debit_amount, credit_amount, type,
CASE WHEN normal_credit_balance = true THEN credit_amount - debit_amount END as credit_balance,
CASE WHEN normal_credit_balance = false THEN debit_amount - credit_amount END as debit_balance
from
(
WITH RECURSIVE children AS (
SELECT id, parent_id, display_name, lft, rgt, type, normal_credit_balance, 0 as newdepth
FROM accounts
WHERE parent_id is null
UNION
SELECT op.id, op.parent_id, op.display_name, op.lft, op.rgt, op.type, op.normal_credit_balance, newdepth + 1
FROM accounts op
JOIN children c ON op.parent_id = c.id
)
SELECT *
FROM children
) accounts_tbl
left join
( SELECT account_id,
SUM( CASE WHEN am.type = 'debit' THEN COALESCE( AMOUNT , 0.0 ) ELSE 0.0 END ) AS debit_amount ,
SUM( CASE WHEN am.type = 'credit' THEN COALESCE( AMOUNT , 0.0 ) ELSE 0.0 END ) AS credit_amount
FROM amounts am
join accounts ac on ac.id = am.account_id
group by account_id, ac.name, ac.type )
as amount_tbl
on accounts_tbl.id = amount_tbl.account_id order by lft
基于金额 table 个条目的示例结果,汇总应如下所示:
| id | name | balance |
|----|----------------|-----------|
| 1 | Assets | 9000 |
| 2 | Current Assets | 9000 |
| 3 | Fixed Assets | 0 |
| 4 | Bank | 9000 |
| 5 | Bank One | 9000 |
| 6 | Bank Two | 0 |
| 7 | Revenue | 10000 |
| 8 | Sales | 10000 |
| 9 | Expenses | 1000 |
| 10 | Rent | 1000 |
如果您使用的是闭包 table 而不是嵌套集(就像我在 中所做的那样),那么您可以使用简单的 JOIN,例如
SELECT
accounts.id,
accounts.title,
SUM(COALESCE(debits.amount,0)) AS debit,
SUM(COALESCE(credit.amount,0)) AS credit
FROM account_tree
LEFT JOIN accounts ON ancestor_id = accounts.id
LEFT JOIN balances AS debits ON account_id = child_id AND type = 'debit'
LEFT JOIN balances AS credits ON account_id = child_id AND type = 'credit'
GROUP BY accounts.id,accounts.title
作为旁注,我建议您将借方和贷方保留在同一行 - 作为 table 余额中的 2 列。
我将从计算每个帐户的“直接”余额开始,使用 left join
和聚合。然后是递归查询:你只需要从叶子遍历树到根,在你走的时候合并平衡。最后一步是聚合。
with recursive
data (id, name, parent_id, balance) as (
select
ac.*,
coalesce(sum(case am.type when 'debit' then - amount when 'credit' then amount end), 0) balance
from accounts ac
left join amounts am on am.account_id = ac.id
group by ac.id
),
cte (id, name, parent_id, balance) as (
select d.* from data d
union all
select d.id, d.name, d.parent_id, d.balance + c.balance
from cte c
inner join data d on d.id = c.parent_id
)
select id, name, sum(balance) from cte group by id, name
我不明白你的结果集中的所有账户最终都是正余额,而有些账户的借方多于贷方(vice-versa)。该查询将借方视为负数,将贷方视为正数。
id | name | sum
-: | :------------- | ----:
1 | Assets | -9000
2 | Current Assets | -9000
3 | Fixed Assets | 0
4 | Bank | -9000
5 | Bank One | -9000
6 | Bank Two | 0
7 | Revenue | 10000
8 | Sales | 10000
9 | Expenses | -1000
10 | Rent | -1000
帐户(link 到其父帐户的主帐户列表(相同 table)) (帐户 table 使用 nested_set 插件维护,因此左、右、深度在 table 中可用,并在 adding/editing 帐户中维护)
| id | name | parent_id |
|----|----------------|-----------|
| 1 | Assets | null |
| 2 | Current Assets | 1 |
| 3 | Fixed Assets | 1 |
| 4 | Bank | 2 |
| 5 | Bank One | 4 |
| 6 | Bank Two | 4 |
| 7 | Revenue | null |
| 8 | Sales | 7 |
| 9 | Expenses | null |
| 10 | Rent | 9 |
条目(存储每笔交易的日期和描述)
| entry_id | date | description |
|----------|------------|--------------------|
| 1 | Mar 3 2020 | Cash Sales |
| 2 | Mar 3 2020 | Cash Paid For Rent |
| 3 | Apr 1 2020 | Owner Withdrawal |
金额(存储复式记账交易的地方)
| entry_id | account_id | type | amount |
|----------|------------|--------|--------|
| 1 | 5 | debit | 10000 |
| 1 | 8 | credit | 10000 |
| 2 | 10 | debit | 1000 |
| 2 | 5 | credit | 1000 |
| | | | |
鉴于上述结构,这是我的要求
- 以树状(分层)结构排列账户并计算个人账户余额(余额可以是debit_balance或credit_balance)
- 分层账户余额,将子余额汇总到父账户
PS: 我确实有上面的 req 1 的解决方案,使用的组合 WITH RECURSIVE sql 函数在账户 table 上分层排列行,然后将结果集与金额 table 相加,金额列(按类型分组后)为每个账户求和. 我很想看看这里的人将如何解决这个问题。 (让我知道你是否想看看到目前为止我得到了什么)
这是为我提供第一个结果集的查询。 (为了简洁起见,我在原始问题中省略了 normal_credit_blance 标志等细节)
select id, parent_id, name, newdepth as depth, debit_amount, credit_amount, type,
CASE WHEN normal_credit_balance = true THEN credit_amount - debit_amount END as credit_balance,
CASE WHEN normal_credit_balance = false THEN debit_amount - credit_amount END as debit_balance
from
(
WITH RECURSIVE children AS (
SELECT id, parent_id, display_name, lft, rgt, type, normal_credit_balance, 0 as newdepth
FROM accounts
WHERE parent_id is null
UNION
SELECT op.id, op.parent_id, op.display_name, op.lft, op.rgt, op.type, op.normal_credit_balance, newdepth + 1
FROM accounts op
JOIN children c ON op.parent_id = c.id
)
SELECT *
FROM children
) accounts_tbl
left join
( SELECT account_id,
SUM( CASE WHEN am.type = 'debit' THEN COALESCE( AMOUNT , 0.0 ) ELSE 0.0 END ) AS debit_amount ,
SUM( CASE WHEN am.type = 'credit' THEN COALESCE( AMOUNT , 0.0 ) ELSE 0.0 END ) AS credit_amount
FROM amounts am
join accounts ac on ac.id = am.account_id
group by account_id, ac.name, ac.type )
as amount_tbl
on accounts_tbl.id = amount_tbl.account_id order by lft
基于金额 table 个条目的示例结果,汇总应如下所示:
| id | name | balance |
|----|----------------|-----------|
| 1 | Assets | 9000 |
| 2 | Current Assets | 9000 |
| 3 | Fixed Assets | 0 |
| 4 | Bank | 9000 |
| 5 | Bank One | 9000 |
| 6 | Bank Two | 0 |
| 7 | Revenue | 10000 |
| 8 | Sales | 10000 |
| 9 | Expenses | 1000 |
| 10 | Rent | 1000 |
如果您使用的是闭包 table 而不是嵌套集(就像我在 中所做的那样),那么您可以使用简单的 JOIN,例如
SELECT
accounts.id,
accounts.title,
SUM(COALESCE(debits.amount,0)) AS debit,
SUM(COALESCE(credit.amount,0)) AS credit
FROM account_tree
LEFT JOIN accounts ON ancestor_id = accounts.id
LEFT JOIN balances AS debits ON account_id = child_id AND type = 'debit'
LEFT JOIN balances AS credits ON account_id = child_id AND type = 'credit'
GROUP BY accounts.id,accounts.title
作为旁注,我建议您将借方和贷方保留在同一行 - 作为 table 余额中的 2 列。
我将从计算每个帐户的“直接”余额开始,使用 left join
和聚合。然后是递归查询:你只需要从叶子遍历树到根,在你走的时候合并平衡。最后一步是聚合。
with recursive
data (id, name, parent_id, balance) as (
select
ac.*,
coalesce(sum(case am.type when 'debit' then - amount when 'credit' then amount end), 0) balance
from accounts ac
left join amounts am on am.account_id = ac.id
group by ac.id
),
cte (id, name, parent_id, balance) as (
select d.* from data d
union all
select d.id, d.name, d.parent_id, d.balance + c.balance
from cte c
inner join data d on d.id = c.parent_id
)
select id, name, sum(balance) from cte group by id, name
我不明白你的结果集中的所有账户最终都是正余额,而有些账户的借方多于贷方(vice-versa)。该查询将借方视为负数,将贷方视为正数。
id | name | sum -: | :------------- | ----: 1 | Assets | -9000 2 | Current Assets | -9000 3 | Fixed Assets | 0 4 | Bank | -9000 5 | Bank One | -9000 6 | Bank Two | 0 7 | Revenue | 10000 8 | Sales | 10000 9 | Expenses | -1000 10 | Rent | -1000