欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

树形关系记录遍历

程序员文章站 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})


相关标签: 遍历 叶子结点