树形关系记录遍历
程序员文章站
2022-06-02 18:27:24
...
基础知识:
ORACLE查询中,存在一些不显示于查询结果中的伪字段;
科目有层级关系,上层级的金额是下层级金额的汇总;
START WITH 指定根节点,CONNECT_BY用于子父连接,prior修饰子\父记录来确定是向下\上遍历,伪字段CONNECT_BY_ISLEAF为1表明该记录为叶子节点记录,CONNECT_BY_ROOT(当前节点)函数返回当前节点的根结点,CONNECY_BY_PATH(当前节点,分割符)可以返回以分割符分割的从根节点到当前节点的路径。
WITH SUBSELECT AS (
SELECT COD_CONTO_ELEGER,CONNECT_BY_ROOT(COD_CONTO_ELEGER) TREE_ROOT ,CONNECT_BY_ISLEAF ISLEAF,SYS_CONNECT_BY_PATH(COD_CONTO_ELEGER,'->') PATH
FROM (
SELECT COD_CONTO_ELEGER,COD_CONTO_ELEGER_PADRE
FROM CONTO_GERARCHIA WHERE COD_CONTO_GERARCHIA='01'
)
START WITH COD_CONTO_ELEGER IN ('100100','110100')
CONNECT BY PRIOR COD_CONTO_ELEGER = COD_CONTO_ELEGER_PADRE
)
SELECT TREE_ROOT, ISLEAF,PATH,SUM((CASE WHEN TREE_ROOT IN ('110100') THEN importo *-1 ELSE importo END) )importo
FROM CONTO_GERARCHIA_ABBI CI
LEFT JOIN ( SELECT COD_CONTO_ELEGER,TREE_ROOT, ISLEAF,PATH FROM SUBSELECT ) T ON T.COD_CONTO_ELEGER = CI.COD_CONTO_ELEGER
left join (select cod_conto,importo from DATI_SALDI_LORDI A WHERE A.COD_AZIENDA IN ('9000') AND A.COD_SCENARIO = '2016ACT' AND A.COD_PERIODO = '02') g on CI.cod_conto=g.cod_conto
WHERE CI.COD_CONTO_ELEGER IN (SELECT COD_CONTO_ELEGER FROM SUBSELECT )
GROUP BY TREE_ROOT, ISLEAF,PATH
ORDER BY TREE_ROOT
查询结果;
TREE_ROOT ISLEAF PATH IMPORTO
1 100100 0 ->100100
2 100100 1 ->100100->100100F10 0
3 100100 1 ->100100->100100F20 575162631.66
4 100100 1 ->100100->100100F30 3307700706.36
5 110100 0 ->110100
6 110100 1 ->110100->110100F10 -200000000
应用:
查询某月科目余额的累计数,以sum函数累计分区中的数据时,发现层级多一级,金额会翻一倍。
解决方案:
只取指定最低层级数据的叶子节点,最后利用查找表影射叶子节点到一级科目,并求和(因为有些子科目是不需要的,不然可直接取一级科目)。
with cc as(
select fyear,lpad(cast(fperiod AS VARCHAR(2)),2,'0') fperiod,subjcode,subjname,subjlev,companycode,companyname, beginbalance,endbalance,localdebitamount, localcreditamount
from [email protected]
where fcurrencyid = 1 and fdetailid = 0
),
S1 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'01' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '01' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '01' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '01'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S2 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'02' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '02' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '02' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '02'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S3 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'03' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '03' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '03' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '03'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S4 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'04' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '04' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '04' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '04'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S5 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'05' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '05' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '05' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '05'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S6 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'06' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '06' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '06' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '06'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S7 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'07' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '07' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '07' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '07'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S8 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'08' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '08' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '08' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '08'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S9 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'09' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '09' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '09' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '09'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S10 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'10' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '10' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '10' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '10'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S11 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'11' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '11' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '11' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '11'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
),
S12 AS (
SELECT fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
SUM(beginbalance) beginbalance,SUM(endbalance) endbalance,SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
SELECT fyear,'11' fperiod,subjcode,subjname,subjlev,companycode,companyname,
CASE FPERIOD WHEN '12' THEN beginbalance ELSE 0 END beginbalance,
CASE FPERIOD WHEN '12' THEN endbalance ELSE 0 END endbalance,
SUM(localdebitamount) localdebitamount,SUM(localcreditamount) localcreditamount
FROM(
select fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,
sum(beginbalance) beginbalance,sum(endbalance) endbalance,sum(localdebitamount) localdebitamount,sum(localcreditamount) localcreditamount
from cc
WHERE FPERIOD <= '12'
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname,beginbalance,endbalance
)
group by fyear,fperiod,subjcode,subjname,subjlev,companycode,companyname
ORDER BY FYEAR,SUBJCODE
)
select YEARMONTH,fyear,fperiod,subjcode,subjname,subjlev, companycode,companyname,beginbalance,endbalance,
SHamount,SHMARK, CLIENT
from (
select YEARMONTH, fyear,fperiod,subjcode,subjname,subjlev, companycode,companyname,beginbalance,endbalance,
SHamount,SHMARK, CLIENT
from (
select SUBJP,SUBJI, fyear||fperiod YEARMONTH, fyear,fperiod,subjcode,subjname,subjlev, companycode,companyname,beginbalance,endbalance,
SHamount,SHMARK, CLIENT
from (
SELECT companycode||fyear||lpad(cast(fperiod AS VARCHAR(2)),2,'0')||SUBSTR( subjcode,1,DECODE(subjlev,1,NULL,2,4,(subjlev -2)*3+4)) SUBJP,
companycode||fyear||lpad(cast(fperiod AS VARCHAR(2)),2,'0')||subjcode SUBJI,
fyear,fperiod,subjcode,subjname,subjlev,M.ELEDIM_OUTPUT1 companycode,companyname,beginbalance,endbalance,
localcreditamount*-1 SHamount,'H' SHMARK,'K3' CLIENT
FROM (
SELECT * FROM S1
UNION ALL
SELECT * FROM S2
UNION ALL
SELECT * FROM S3
UNION ALL
SELECT * FROM S4
UNION ALL
SELECT * FROM S5
UNION ALL
SELECT * FROM S6
UNION ALL
SELECT * FROM S7
UNION ALL
SELECT * FROM S8
UNION ALL
SELECT * FROM S9
UNION ALL
SELECT * FROM S10
UNION ALL
SELECT * FROM S11
UNION ALL
SELECT * FROM S12
)
S
LEFT JOIN MAP_REGOLA_TAB_ELEMENTO M ON M.COD_REGOLA_TAB = 'MAP_BUKRS_K3' AND M.COD_MAPPATURA = 'HI_DATA_GL' AND M.ELEDIM_INPUT2 = S.companycode
)
WHERE CONNECT_BY_ISLEAF = 1
start with SUBJLEV = 1
connect by prior SUBJI = SUBJP
)
union all
select YEARMONTH, fyear,fperiod,subjcode,subjname,subjlev, companycode,companyname,beginbalance,endbalance,
SHamount,SHMARK, CLIENT
from (
select SUBJP,SUBJI, fyear||fperiod YEARMONTH, fyear,fperiod,subjcode,subjname,subjlev, companycode,companyname,beginbalance,endbalance,
SHamount,SHMARK, CLIENT
FROM (
SELECT companycode||fyear||lpad(cast(fperiod AS VARCHAR(2)),2,'0')||SUBSTR( subjcode,1,DECODE(subjlev,1,NULL,2,4,(subjlev -2)*3+4)) SUBJP,
companycode||fyear||lpad(cast(fperiod AS VARCHAR(2)),2,'0')||subjcode SUBJI,
fyear,fperiod,subjcode,subjname,subjlev,M.ELEDIM_OUTPUT1 companycode,companyname,0 beginbalance,0 endbalance,
localdebitamount SHamount,'S' SHMARK,'K3' CLIENT
FROM (
SELECT * FROM S1
UNION ALL
SELECT * FROM S2
UNION ALL
SELECT * FROM S3
UNION ALL
SELECT * FROM S4
UNION ALL
SELECT * FROM S5
UNION ALL
SELECT * FROM S6
UNION ALL
SELECT * FROM S7
UNION ALL
SELECT * FROM S8
UNION ALL
SELECT * FROM S9
UNION ALL
SELECT * FROM S10
UNION ALL
SELECT * FROM S11
UNION ALL
SELECT * FROM S12
)
S
LEFT JOIN MAP_REGOLA_TAB_ELEMENTO M ON M.COD_REGOLA_TAB = 'MAP_BUKRS_K3' AND M.COD_MAPPATURA = 'HI_DATA_GL' AND M.ELEDIM_INPUT2 = S.companycode
)
WHERE CONNECT_BY_ISLEAF = 1
start with SUBJLEV = 1
connect by prior SUBJI = SUBJP
)
)
where companycode IN ({IN-ENTITY}) AND YEARMONTH IN ({IN-YEARMONTH})
推荐阅读
-
python记录_day17 类与类之间的关系
-
EF更新多对多关系表中记录的时候,无法更新关系表的问题。
-
mssql sqlserver sql脚本自动遍历重复生成指定表记录
-
关于关系数据库如何快速查询表的记录数详解
-
[MAKE]从makefile获取代码树形结构关系
-
bootstrap Treeview 树形结构 无限极二维数组层级关系
-
PyQt5 QTreeWidget 树形结构递归遍历当前所有节点的实现
-
mysql存储过程基础之遍历多表记录后插入第三方表中详解
-
关于html嵌入xml数据岛如何穿过树形结构关系的问题
-
为何mysql_fetch_array/assoc + foreach只能遍历一条记录