我的数据库是sqlserver,我的凭证表 的字段为
表名:会计分录
字段名 :科目代码,科目名称,一级代码 ,借方 ,贷方
我想得通过查询得到 科目余额表,其结构如下:
科目代码,科目名称,一级代码 ,期初 ,借方 ,贷方 ,期末。
主要思路:
我用了一个sqlserver的函数,函数中主要有几部分构成
比如查 2022年度的科目做余额表,我将起止年度分成两部分,
(1)第一部分查 2022年以前的借贷方数据以生成期初数据,将日期作为参数带入,便于扩展与增加灵活性,具体对应的代码 是
(SELECT 科目代码 as 一级代码, 科目名称,(借方-贷方) as 期初,0 as 借方 ,0 as 贷方,(借方-贷方) as 期末
from 会计分录 where 日期<@rqa
(2)第二部分查 2022年1-12月以生成当期的期初、期末、借方 、贷方 数据,将日期作为参数带入,便于扩展与增加灵活性,具体对应的代码如下:
SELECT 科目代码 as 一级代码 ,科目名称, 0 as 期初, 借方 , 贷方,(借方-贷方) as 期末
from 会计分录 where 日期>=@rqb and 日期<=@rqc ) a
(3)将这两段数据进行union合并成一个数据集
(SELECT 科目代码 as 一级代码, 科目名称,(借方-贷方) as 期初,0 as 借方 ,0 as 贷方,(借方-贷方) as 期末
from 会计分录 where 日期<@rqa
UNION ALL
SELECT 科目代码 as 一级代码 ,科目名称, 0 as 期初, 借方 , 贷方,(借方-贷方) as 期末
from 会计分录 where 日期>=@rqb and 日期<=@rqc )
(4) 上面得到了构成科目余额表的原始数据,我们对其进行一个分类汇总,按科目进行分类,总体代码
select MAX(a.一级代码) AS 科目代码,max(a.科目名称) as 科目名称,
sum(a.期初) as 期初, sum(a.借方) as 借方 , sum(a.贷方) as 贷方, sum( a.期末) as 期末 FROM
(SELECT 科目代码 as 一级代码, 科目名称,(借方-贷方) as 期初,0 as 借方 ,0 as 贷方,(借方-贷方) as 期末
from 会计分录 where 日期<@rqa
UNION ALL
SELECT 科目代码 as 一级代码 ,科目名称, 0 as 期初, 借方 , 贷方,(借方-贷方) as 期末
from 会计分录 where 日期>=@rqb and 日期<=@rqc ) a
GROUP BY 一级代码
(5)、以上就是我们查询数据的全部内容,因为考虑到接受起止时间,因此,我将其做成了一个sqlserver的函数,全部代码 如下
create FUNCTION kmallmx(@rqa datetime,@rqb datetime,@rqc datetime)
RETURNS TABLE
AS
RETURN
select MAX(a.一级代码) AS 科目代码,max(a.科目名称) as 科目名称,
sum(a.期初) as 期初, sum(a.借方) as 借方 , sum(a.贷方) as 贷方, sum( a.期末) as 期末 FROM
(SELECT 科目代码 as 一级代码, 科目名称,(借方-贷方) as 期初,0 as 借方 ,0 as 贷方,(借方-贷方) as 期末
from 会计分录 where 日期<@rqa
UNION ALL
SELECT 科目代码 as 一级代码 ,科目名称, 0 as 期初, 借方 , 贷方,(借方-贷方) as 期末
from 会计分录 where 日期>=@rqb and 日期<=@rqc ) a
GROUP BY 一级代码 having abs(sum(期初))>1 or abs(sum(借方))>1 or abs(sum(贷方))>1 OR abs(sum(期末))>1
(6)、最终的调用就非常简单 了,给出起止时间就是科目余额表
procedure kmyeb.KMYEB1J(rq1, rq2: tdatetime);
var
STR: string;
begin
qry1j.Close;
qry1j.Connection := fcon;
qry1j.Close;
qry1j.sql.clear;
qry1j.sql.add('select a.科目代码,B.科目名称,a.期初,a.借方,a.贷方,a.期末 from kmonett(:rq1,:rq2,:rq3)');
qry1j.sql.add(' A LEFT JOIN 一级科目 b ON a.科目代码=b.科目代码 ');
qry1j.sql.add(' order by a.科目代码');
qry1j.Parameters.ParamByName('RQ1').Value := rq1;
qry1j.Parameters.ParamByName('RQ2').Value := rq1;
qry1j.Parameters.ParamByName('RQ3').Value := rq2;
qry1j.Open;
end;
这种适合一般的中小企业,数量量不大,我公司十年的数据将近四十万条,这样进行科目余额表的统计也非常快,不存在延迟等时间上不能接受的情况 ,具有一定的适用性。因为我是从财务系统中导账出来进行分析的,不是完整的财务软件,因此是一种较快的方式。
可能规范的用法,尽量减少访问全部数据,将每月的科目余额表作单独的存储,并且对会计凭证要进行记账结账,这样保证数据的访问量较小,并且更高效,只不过开发上麻烦一些。上述的用法只适合我们分析数据去用。