请问您见过最惊艳的sql查询语句是什么?
作者:卡卷网发布时间:2025-03-07 21:44浏览数量:108次评论数量:0次
财务里面,一条 SQL 算出资产负债表,要求每个项都是根据自定义公式计算得出,还要考虑已结账、未结账、会计科目是否重分类等不同的情况:
SELECT T.* FROM (
/** 查询整体思路说明
【资产负债表】需要根据【科目余额表】得出,而科目余额表的计算需要考虑所选会计期间
包含【已结账区间】和【未结账区间】:
1. 对于已结账区间,应从科目余额表 (accounting_balance) 中直接取出结果。
2. 对于未结账的区间,应通过期间内凭证表(accounting_voucher、accounting_voucher_entry)
,实时汇总得出。
**/
WITH
-- 准备账套科目表
s AS (
SELECT s.id, s.code, s.name, s.direction, s.is_leaf, s.level
FROM account_subject s
LEFT JOIN account_subject_id i
ON s.id = i.s_id
WHERE (i.a_id = @1-ACCOUNT_ID@ OR i.a_id is NULL)
)
-- 查询【会计期间】期初余额,本年累计发生额,若上月未结账则查不出记录。
, bb AS (
SELECT subject_id
, beginning_debit
, beginning_credit
, accumulated_debit
, accumulated_credit
, incurred_debit
, incurred_credit
FROM accounting_balance
WHERE account_id = @1-ACCOUNT_ID@
AND period = @11-PERIOD@
)
-- 查询会计期间上个月是否结账,方便后面查询做判断:对于结账的会计期间,应直接从科目余额表 accounting_balance 中取数。
, bb_count AS (
SELECT COUNT(*) as num FROM bb
)
/** 以下整体是查出每个科目(含非叶子节点)余额的期末余额、年初余额 **/
, ba AS (
SELECT S.id AS subject_id
, S.name
, S.code
, S.is_leaf
, S.direction
, SUM(IF(B.direction = '借'
, (B.beginning_balance + B.incurred_debit - B.incurred_credit)
, (B.beginning_balance + B.incurred_credit - B.incurred_debit)
) * IF(S.direction = B.direction, 1, -1)
) AS balance -- 期末余额
, SUM(IF(B.direction = '借'
, (B.beginning_balance - B.accumulated_debit + B.accumulated_credit)
, (B.beginning_balance - B.accumulated_credit + B.accumulated_debit)
) * IF(S.direction = B.direction, 1, -1)
) AS year_beginning_balance -- 年初余额
, SUM(B.incurred_debit) AS incurred_debit --本期借方发生额
, SUM(B.incurred_credit) AS incurred_credit --本期贷方发生额
FROM
s AS S,
(
/* 查询期初余额、期初时本年累计发生额。*/
SELECT s.id as subject_id, s.code, s.direction
, IF(s.direction = '借'
, IFNULL(bb.beginning_debit
, IFNULL(debit_1, 0) + IFNULL(debit_2, 0) - IFNULL(credit_2, 0)
)
, IFNULL(bb.beginning_credit
, IFNULL(credit_1, 0) + IFNULL(credit_2, 0) - IFNULL(debit_2, 0)
)
) AS beginning_balance
, IFNULL(bb.accumulated_debit, IFNULL(b1.acc_debit_1, 0) + IFNULL(debit_2, 0)) AS accumulated_debit
, IFNULL(bb.accumulated_credit, IFNULL(b1.acc_credit_1, 0) + IFNULL(credit_2, 0)) AS accumulated_credit
, IFNULL(b3.incurred_debit, 0) + IFNULL(b4.incurred_debit, 0) AS incurred_debit
, IFNULL(b3.incurred_credit, 0) + IFNULL(b4.incurred_credit, 0) AS incurred_credit
FROM
s
LEFT JOIN bb
ON s.id = bb.subject_id
LEFT JOIN
( -- 查出账户【当前会计期间】各个科目期初余额、本年累计发生额
SELECT b.subject_id
, b.beginning_debit as debit_1
, b.beginning_credit as credit_1
, b.accumulated_debit as acc_debit_1
, b.accumulated_credit as acc_credit_1
FROM accounting_balance b, bb_count
WHERE bb_count.num = 0 -- 仅当数据库的科目余额表没有【所查询期间】的结账记录才查询。
AND b.account_id = @1-ACCOUNT_ID@
AND b.period = @1-ACCOUNT_CURRENT_PERIOD@
) AS b1
ON s.id = b1.subject_id
LEFT JOIN
( -- 查出账户【当前会计期间】到【查询期间】累计发生额
SELECT e.subject_id
, SUM(e.debit * IF(e.is_reversal, -1, 1)) as debit_2
, SUM(e.credit * IF(e.is_reversal, -1, 1)) as credit_2
FROM accounting_voucher_entry e, bb_count
WHERE bb_count.num = 0 -- 仅当数据库的科目余额表没有这一期的结账记录,才查询。
AND e.status = 1
AND e.account_id = @1-ACCOUNT_ID@
AND e.period >= @1-ACCOUNT_CURRENT_PERIOD@
AND e.period < @11-PERIOD@
GROUP BY e.subject_id
) AS b2
ON s.id = b2.subject_id
/* 以上是查出期初余额、期初时本年累计发生额。 */
LEFT JOIN
-- 查询期间内所有科目借贷发生额 = 已结账累计借贷发生额(b3) + 未结账累计借贷发生额(b4)
( -- 查询已结账累计借贷发生额
SELECT b.subject_id
, SUM(IFNULL(b.incurred_debit, 0)) AS incurred_debit
, SUM(IFNULL(b.incurred_credit, 0)) AS incurred_credit
FROM accounting_balance b
WHERE b.account_id = @1-ACCOUNT_ID@
AND b.period >= @11-PERIOD@
AND b.period <= #@1-ACCOUNT_CURRENT_PERIOD@ < @11-PERIOD@ ? @1-ACCOUNT_CURRENT_PERIOD@ : @11-PERIOD@#
GROUP BY subject_id
) AS b3
ON s.id = b3.subject_id
LEFT JOIN
( -- 查询未结账累计借贷发生额
SELECT e.subject_id
, SUM(e.debit * IF(e.is_reversal, -1, 1)) as incurred_debit
, SUM(e.credit * IF(e.is_reversal, -1, 1)) as incurred_credit
FROM accounting_voucher_entry e
WHERE e.status = 1 -- 只统计已过账凭证
AND e.account_id = @1-ACCOUNT_ID@
AND e.period >= #@1-ACCOUNT_CURRENT_PERIOD@ > @11-PERIOD@ ? @1-ACCOUNT_CURRENT_PERIOD@ : @11-PERIOD@#
AND e.period <= @11-PERIOD@
GROUP BY subject_id
) b4
ON s.id = b4.subject_id
) AS B
WHERE B.code LIKE CONCAT(S.code, '%')
GROUP BY S.id, S.code, S.name, S.direction, S.is_leaf
) /** end for ba 以上整体是查出每个科目(含非叶子节点)余额的期末余额 **/
-- 根据科目余额表 ba 算出资产负债表中所有计算方式为【科目余额表项求和】的报告项
-- 其中 A 表为根据公式表直接结算的结果,B 表为重分类计算结果(只有 6 个科目需要重分类计算)。
, bs_0 AS (
SELECT A.id
, IF(@11-RECLASSIFY@ > 0, IFNULL(B.balance, A.balance), A.balance) AS balance
, IF(@11-RECLASSIFY@ > 0, IFNULL(B.year_beginning_balance, A.year_beginning_balance), A.year_beginning_balance) AS year_beginning_balance
FROM
(
SELECT sh.id
, sh.name
, SUM(ba.balance * fi.sign) AS balance
, SUM(ba.year_beginning_balance * fi.sign) AS year_beginning_balance
FROM account_balance_sheet_item sh
LEFT JOIN account_balance_sheet_formula_item fi
ON sh.id = fi.item_id
LEFT JOIN ba
ON fi.formula_item_id = ba.subject_id
WHERE sh.calc_method = '科目余额表项求和'
GROUP BY sh.id
) A
LEFT JOIN
( /** 重分类计算 **/
SELECT '应收账款' AS name
, SUM(IF( (direction = '借' AND balance > 0) OR (direction = '贷' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '借' AND year_beginning_balance > 0) OR (direction = '贷' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('应收账款', '预收账款')
)
UNION ALL
SELECT '预付账款' AS name
, SUM(IF( (direction = '借' AND balance > 0) OR (direction = '贷' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '借' AND year_beginning_balance > 0) OR (direction = '贷' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('预付账款', '应付账款')
)
UNION ALL
SELECT '应付账款' AS name
, SUM(IF( (direction = '贷' AND balance > 0) OR (direction = '借' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '贷' AND year_beginning_balance > 0) OR (direction = '借' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('应付账款', '预付账款')
)
UNION ALL
SELECT '预收账款' AS name
, SUM(IF( (direction = '贷' AND balance > 0) OR (direction = '借' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '贷' AND year_beginning_balance > 0) OR (direction = '借' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('预收账款', '应收账款')
)
UNION ALL
SELECT '其他应收款' AS name
, SUM(IF( (direction = '借' AND balance > 0) OR (direction = '贷' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '借' AND year_beginning_balance > 0) OR (direction = '贷' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('其他应收款', '其他应付款')
)
UNION ALL
SELECT '其他应付款' AS name
, SUM(IF( (direction = '贷' AND balance > 0) OR (direction = '借' AND balance < 0)
, ABS(balance)
, 0)
) AS balance
, SUM(IF( (direction = '贷' AND year_beginning_balance > 0) OR (direction = '借' AND year_beginning_balance < 0)
, ABS(year_beginning_balance)
, 0)
) AS year_beginning_balance
FROM ba WHERE code in
( SELECT s.code FROM s, s as s0
WHERE IF(@11-RECLASSIFY@ = 2, s.is_leaf, s.level = 0)
AND s.code LIKE CONCAT(s0.code, '%')
AND s0.name in ('其他应付款', '其他应收款')
)
) B /** 以上重分类计算 **/
ON A.name = B.name
)
-- 根据 bs_0 算出资产负债表中有依赖【本表内项求和】的报告项
, bs_1 AS (
SELECT sh.id
, SUM(bs_0.balance * fi.sign) AS balance
, SUM(bs_0.year_beginning_balance * fi.sign) AS year_beginning_balance
FROM account_balance_sheet_item sh
LEFT JOIN account_balance_sheet_formula_item fi
ON sh.id = fi.item_id
LEFT JOIN bs_0
ON fi.formula_item_id = bs_0.id
WHERE sh.calc_method = '本表内项求和'
GROUP BY sh.id
)
-- 根据 bs_0, bs_1 汇总成最终的资产负债表 bs
, bs AS (
SELECT sh.id
, sh.name
, sh.row_num
, sh.ord
, sh.level
, sh.calc_method
, sh.side
, bs_2.balance
, bs_2.year_beginning_balance
FROM account_balance_sheet_item sh
LEFT JOIN (
SELECT id, balance, year_beginning_balance FROM bs_0
UNION
SELECT id, balance, year_beginning_balance FROM bs_1
) AS bs_2
ON sh.id = bs_2.id
ORDER BY sh.ord
)
-- 以下是把资产负债表 拆分成左右结构做展示
SELECT L.id AS l_id
, L.name AS l_name
, L.row_num AS l_row_num
, L.balance AS l_balance
, L.level AS l_level
, L.calc_method AS l_calc_method
, L.year_beginning_balance l_b_balance
, ' ' m
, R.id AS r_id
, R.name AS r_name
, R.row_num AS r_row_num
, R.balance AS r_balance
, R.level AS r_level
, R.calc_method AS r_calc_method
, R.year_beginning_balance r_b_balance
, ' ' AS p
, ' ' AS view_formula
FROM bs AS L
LEFT JOIN
bs AS R
ON L.ord + 32 = R.ord
WHERE L.side = '左' AND R.side = '右'
) AS T
效果:
现在已经可以直接写 SQL 就能开发各种复杂的企业级管理系统了: enhancer.io
免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。
相关推荐

你 发表评论:
欢迎