上一篇随笔中写到:业务要求开发一个报表请求,输出指定期间内的客户余额变动明细的数据报表,自己折腾了好久,再加上向技术大佬的跪地请教学习,终于是完成的相关需求的开发实现。呼~~~
  但是!但是!但是!一个类似的业务报表需求来了,是要求输出AP里面供应商的余额变动明细数据报表...T_T
  一个是AR里面的数据信息,一个又是AP里面的数据信息,现在有了书写AR的经验积累,一开始的时候就确认了,最后的数据输出也是要用到 full outer join 的关联方法的。因为在AP里面的场景没有AR里面的那么多,就只有 AP_INVOICES 的发票场景,以及 AP_PAYMENTS 的发票支付场景,所以构建的SQL会简单一些,但也还是要通过子分类账 sla 的表(xla)去透视关联。。。
  首先查验需求中要求输出的科目所对应的日记账数据,发现这部分日记账数据的来源 je_source 同样不仅仅只有从 AP 模块传送的数据,同样有通过 spreadsheet 导入的数据以及其他来源的数据,这样的化,就要和客户报表的数据类似,分为2部分去输出,最后将结果进行 union all 的拼接即可。
  首先构建从 AP 传送的数据查询SQL(最初版):

SLA_AP穿透查询SQL【点击查看代码】
SELECT query_source_net.segment3,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 3,
                                             x_seg_val => query_source_net.segment3) segment3_desc,
       query_source_net.segment8,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 8,
                                             x_seg_val => query_source_net.segment8) segment8_desc,
       query_source_net.vendor_num,
       query_source_net.vendor_name,
       'CNY' currency_code,
       nvl(query_source_bal.begin_bal, 0) begin_bal,
       query_source_net.net_dr,
       query_source_net.net_cr,
       (nvl(query_source_bal.begin_bal, 0) + query_source_net.net_dr -
       query_source_net.net_cr) end_bal
  FROM (SELECT /*+parallel(8)*/
         t.segment3,
         t.segment8,
         t.vendor_num,
         t.vendor_name,
         'CNY' currency_code,
         SUM(t.accounted_dr) net_dr,
         SUM(t.accounted_cr) net_cr
          FROM (SELECT pv.vendor_name,
                       pv.segment1 vendor_num,
                       gcc.segment3,
                       gcc.segment8,
                       nvl(xal.accounted_dr, 0) accounted_dr,
                       nvl(xal.accounted_cr, 0) accounted_cr
                  FROM ap.ap_invoices_all           ai,
                       apps.po_vendors              pv,
                       xla.xla_transaction_entities xte,
                       gl.gl_period_statuses        gps,
                       xla.xla_ae_headers           xah,
                       xla.xla_ae_lines             xal,
                       gl.gl_code_combinations      gcc
                 WHERE ai.vendor_id = pv.vendor_id
                   AND xte.entity_id = xah.entity_id
                   AND xte.application_id = xah.application_id
                   AND xah.ae_header_id = xal.ae_header_id
                   AND xah.application_id = xal.application_id
                   AND xah.ledger_id = gps.ledger_id
                   AND xah.period_name = gps.period_name
                   AND xah.application_id = gps.application_id
                   AND nvl(ai.org_id, 81) = 81
                   AND xah.ledger_id = 2021
                   AND xal.code_combination_id = gcc.code_combination_id
                   AND gps.effective_period_num BETWEEN g_period_from_num AND
                       g_period_to_num
                   AND gcc.segment1 = '0010'
                   AND (gcc.segment3 LIKE '203%' OR
                       gcc.segment3 IN
                       ('1150000', '2090100', '1190100', '1160000'))
                   AND xte.application_id = 200
                   AND xte.entity_code = 'AP_INVOICES'
                   AND xte.source_id_int_1 = ai.invoice_id
                UNION ALL
                SELECT pv.vendor_name,
                       pv.segment1 vendor_num,
                       gcc.segment3,
                       gcc.segment8,
                       nvl(xal.accounted_dr, 0) accounted_dr,
                       nvl(xal.accounted_cr, 0) accounted_cr
                  FROM ap.ap_checks_all             ac,
                       apps.po_vendors              pv,
                       xla.xla_transaction_entities xte,
                       gl.gl_period_statuses        gps,
                       xla.xla_ae_headers           xah,
                       xla.xla_ae_lines             xal,
                       gl.gl_code_combinations      gcc
                 WHERE ac.vendor_id = pv.vendor_id
                   AND xte.entity_id = xah.entity_id
                   AND xte.application_id = xah.application_id
                   AND xah.ae_header_id = xal.ae_header_id
                   AND xah.application_id = xal.application_id
                   AND xah.ledger_id = gps.ledger_id
                   AND xah.period_name = gps.period_name
                   AND xah.application_id = gps.application_id
                   AND nvl(ac.org_id, 81) = 81
                   AND xah.ledger_id = 2021
                   AND xal.code_combination_id = gcc.code_combination_id
                   AND gcc.segment1 = '0010'
                   AND gps.effective_period_num BETWEEN 20240001 AND 20240001
                   AND (gcc.segment3 LIKE '203%' OR
                       gcc.segment3 IN
                       ('1150000', '2090100', '1190100', '1160000'))
                   AND xte.application_id = 200
                   AND xte.entity_code = 'AP_PAYMENTS'
                   AND xte.source_id_int_1 = ac.check_id) t
         GROUP BY t.vendor_name, t.vendor_num, t.segment3, t.segment8) query_source_net,
       (SELECT aaa.segment3,
               aaa.segment8,
               aaa.vendor_num,
               aaa.vendor_name,
               'CNY' currency_code,
               nvl(SUM(aaa.beg_bal), 0) begin_bal
          FROM (SELECT pv.vendor_name,
                       pv.segment1 vendor_num,
                       gcc.segment3,
                       gcc.segment8,
                       nvl(xal.accounted_dr, 0) - nvl(xal.accounted_cr, 0) beg_bal
                  FROM ap.ap_invoices_all           aia,
                       apps.po_vendors              pv,
                       xla.xla_transaction_entities xte,
                       xla.xla_ae_headers           xah,
                       xla.xla_ae_lines             xal,
                       gl.gl_code_combinations      gcc
                 WHERE aia.invoice_id = xte.source_id_int_1
                   AND aia.invoice_num = xte.transaction_number
                   AND aia.vendor_id = pv.vendor_id
                   AND xte.application_id = xah.application_id
                   AND xte.entity_id = xah.entity_id
                   AND xte.entity_code = 'AP_INVOICES'
                   AND xah.ae_header_id = xal.ae_header_id
                   AND xah.application_id = xal.application_id
                   AND xal.code_combination_id = gcc.code_combination_id
                   AND nvl(aia.org_id, 81) = 81
                   AND xah.ledger_id = 2021
                   AND aia.gl_date <
                       (SELECT s.start_date
                          FROM gl.gl_period_statuses s
                         WHERE s.application_id = 200
                           AND s.ledger_id = 2021
                           AND s.period_name = '24-Jan')
                   AND gcc.segment1 = '0010'
                   AND (gcc.segment3 LIKE '203%' OR
                       gcc.segment3 IN
                       ('1150000', '2090100', '1190100', '1160000'))
                   AND gcc.summary_flag = 'N'
                UNION ALL
                SELECT pv.vendor_name,
                       pv.segment1 vendor_num,
                       gcc.segment3,
                       gcc.segment8,
                       nvl(ac.amount, 0) beg_bal
                  FROM ap.ap_checks_all             ac,
                       apps.po_vendors              pv,
                       xla.xla_transaction_entities xte,
                       xla.xla_ae_headers           xah,
                       xla.xla_ae_lines             xal,
                       gl.gl_code_combinations      gcc
                 WHERE ac.vendor_id = pv.vendor_id
                   AND xte.source_id_int_1 = ac.check_id
                   AND xte.entity_code = 'AP_PAYMENTS'
                   AND xte.application_id = xah.application_id
                   AND xte.entity_id = xah.entity_id
                   AND xah.application_id = xal.application_id
                   AND xah.ae_header_id = xal.ae_header_id
                   AND xal.code_combination_id = gcc.code_combination_id
                   AND nvl(ac.org_id, 81) = 81
                   AND xah.ledger_id = 2021
                   AND gcc.segment1 = '0010'
                   AND (gcc.segment3 LIKE '203%' OR
                       gcc.segment3 IN
                       ('1150000', '2090100', '1190100', '1160000'))
                   AND gcc.summary_flag = 'N'
                   AND trunc(ac.check_date) <
                       (SELECT s.start_date
                          FROM gl.gl_period_statuses s
                         WHERE s.application_id = 200
                           AND s.ledger_id = 2021
                           AND s.period_name = '24-Jan')) aaa
         GROUP BY aaa.vendor_name,
                  aaa.vendor_num,
                  aaa.segment3,
                  aaa.segment8) query_source_bal
 WHERE 1 = 1
   AND query_source_net.segment3 = query_source_bal.segment3(+)
   AND query_source_net.segment8 = query_source_bal.segment8(+)
   AND query_source_net.vendor_num = query_source_bal.vendor_num(+)
   AND query_source_net.vendor_name = query_source_bal.vendor_name(+);

  构建初版其他日记账来源的数据查询SQL:
其他日记账来源查询SQL【点击查看代码】
SELECT /*+parallel(8)*/
 oth_net.segment3,
 gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                       x_seg_num => 3,
                                       x_seg_val => oth_net.segment3) segment3_desc,
 oth_net.segment8,
 gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                       x_seg_num => 8,
                                       x_seg_val => oth_net.segment8) segment8_desc,
 oth_net.vendor_num,
 oth_net.vendor_name,
 'CNY' currency_code,
 nvl(oth_bal.account_bal, 0) begin_bal,
 oth_net.account_dr,
 oth_net.account_cr,
 (nvl(oth_bal.account_bal, 0) + oth_net.account_dr - oth_net.account_cr) oth_end_bal
  FROM (SELECT pv.vendor_name,
               pv.segment1 vendor_num,
               gcc.segment3,
               gcc.segment8,
               SUM(nvl(l.accounted_dr, 0)) account_dr,
               SUM(nvl(l.accounted_cr, 0)) account_cr
          FROM gl.gl_je_headers        h,
               gl.gl_je_lines          l,
               gl.gl_period_statuses   gps,
               gl.gl_code_combinations gcc,
               ap.ap_invoices_all      aia,
               apps.po_vendors         pv
         WHERE h.ledger_id = 2021
           AND h.je_header_id = l.je_header_id
           AND h.status = 'P'
           AND h.ledger_id = gps.ledger_id
           AND h.period_name = gps.period_name
           AND h.ledger_id = aia.set_of_books_id(+)
           AND gcc.code_combination_id =
               aia.accts_pay_code_combination_id(+)
           AND aia.vendor_id = pv.vendor_id(+)
           AND nvl(aia.org_id, 81) = 81
           AND gps.application_id = 200
           AND l.code_combination_id = gcc.code_combination_id
           AND gps.effective_period_num BETWEEN 20240001 AND 20240001
           AND h.je_source <> 'Payables'
           AND gcc.segment1 = '0010'
           AND (gcc.segment3 LIKE '203%' OR
               gcc.segment3 IN ('1150000', '2090100', '1190100', '1160000'))
         GROUP BY pv.vendor_name, pv.segment1, gcc.segment3, gcc.segment8) oth_net,
       (SELECT pv.vendor_name,
               pv.segment1 vendor_num,
               gcc.segment3,
               gcc.segment8,
               SUM(nvl(l.accounted_dr, 0) - nvl(l.accounted_cr, 0)) account_bal
          FROM gl.gl_je_headers        h,
               gl.gl_je_lines          l,
               gl.gl_period_statuses   gps,
               gl.gl_code_combinations gcc,
               ap.ap_invoices_all      aia,
               apps.po_vendors         pv
         WHERE h.ledger_id = 2021
           AND h.je_header_id = l.je_header_id
           AND h.status = 'P'
           AND h.ledger_id = gps.ledger_id
           AND h.period_name = gps.period_name
           AND h.ledger_id = aia.set_of_books_id(+)
           AND gcc.code_combination_id =
               aia.accts_pay_code_combination_id(+)
           AND aia.vendor_id = pv.vendor_id(+)
           AND nvl(aia.org_id, 81) = 81
           AND gps.application_id = 200
           AND l.code_combination_id = gcc.code_combination_id
           AND gps.effective_period_num < 20240001
           AND h.je_source <> 'Payables'
           AND gcc.segment1 = '0010'
           AND (gcc.segment3 LIKE '203%' OR
               gcc.segment3 IN ('1150000', '2090100', '1190100', '1160000'))
         GROUP BY pv.vendor_name, pv.segment1, gcc.segment3, gcc.segment8) oth_bal
 WHERE 1 = 1
   AND oth_net.segment3 = oth_bal.segment3(+)
   AND oth_net.segment8 = oth_bal.segment8(+)
 ORDER BY segment3, segment8, vendor_num;

  根据之前的经验,将两串SQL使用全外连接 `full outer join` 进行关联合并,并使用cte表达式对SQL进行优化调整,最后输出的完整代码SQL为:
WITH common_data /*+ MATERIALIZE */
 AS
 (SELECT gcc.segment3,
         gcc.segment8,
         xal.accounted_dr,
         xal.accounted_cr,
         gps.effective_period_num,
         xte.entity_code,
         xte.source_id_int_1
    FROM xla.xla_transaction_entities xte,
         gl.gl_period_statuses        gps,
         xla.xla_ae_headers           xah,
         xla.xla_ae_lines             xal,
         gl.gl_code_combinations      gcc
   WHERE xte.entity_id = xah.entity_id
     AND xte.application_id = xah.application_id
     AND xah.ae_header_id = xal.ae_header_id
     AND xah.application_id = xal.application_id
     AND xah.ledger_id = gps.ledger_id
     AND xah.period_name = gps.period_name
     AND xah.application_id = gps.application_id
     AND xah.ledger_id = 2021
     AND xal.code_combination_id = gcc.code_combination_id
     AND gcc.segment1 = '0010'
     AND (gcc.segment3 LIKE '203%' OR
         gcc.segment3 IN ('1150000', '2090100', '1190100', '1160000'))
     AND xte.application_id = 200),
source_net AS
/*--子模块发生额数据--*/
 (SELECT t.segment3,
         t.segment8,
         t.vendor_num,
         t.vendor_name,
         'CNY' currency_code,
         SUM(t.accounted_dr) net_dr,
         SUM(t.accounted_cr) net_cr
    FROM (SELECT pv.vendor_name,
                 pv.segment1 vendor_num,
                 cd.segment3,
                 cd.segment8,
                 nvl(cd.accounted_dr, 0) accounted_dr,
                 nvl(cd.accounted_cr, 0) accounted_cr
            FROM ap.ap_invoices_all ai, apps.po_vendors pv, common_data cd
           WHERE ai.vendor_id = pv.vendor_id
             AND cd.entity_code = 'AP_INVOICES'
             AND cd.source_id_int_1 = ai.invoice_id
             AND nvl(ai.org_id, 81) = 81
             AND cd.effective_period_num BETWEEN 20240001 AND 20240001
          UNION ALL
          SELECT pv.vendor_name,
                 pv.segment1 vendor_num,
                 cd.segment3,
                 cd.segment8,
                 nvl(cd.accounted_dr, 0) accounted_dr,
                 nvl(cd.accounted_cr, 0) accounted_cr
            FROM ap.ap_checks_all ac, apps.po_vendors pv, common_data cd
           WHERE ac.vendor_id = pv.vendor_id
             AND cd.entity_code = 'AP_PAYMENTS'
             AND cd.source_id_int_1 = ac.check_id
             AND nvl(ac.org_id, 81) = 81
             AND cd.effective_period_num BETWEEN 20240001 AND 20240001) t
   GROUP BY t.vendor_name, t.vendor_num, t.segment3, t.segment8),
source_begin AS
/*--子模块期初数据--*/
 (SELECT t.segment3,
         t.segment8,
         t.vendor_num,
         t.vendor_name,
         'CNY' currency_code,
         SUM(nvl(t.beg_bal, 0)) begin_bal
    FROM (SELECT pv.vendor_name,
                 pv.segment1 vendor_num,
                 cd.segment3,
                 cd.segment8,
                 nvl(cd.accounted_dr, 0) - nvl(cd.accounted_cr, 0) beg_bal
            FROM ap.ap_invoices_all ai, apps.po_vendors pv, common_data cd
           WHERE ai.vendor_id = pv.vendor_id
             AND cd.entity_code = 'AP_INVOICES'
             AND cd.source_id_int_1 = ai.invoice_id
             AND nvl(ai.org_id, 81) = 81
             AND cd.effective_period_num < 20240001
          UNION ALL
          SELECT pv.vendor_name,
                 pv.segment1 vendor_num,
                 cd.segment3,
                 cd.segment8,
                 nvl(cd.accounted_dr, 0) - nvl(cd.accounted_cr, 0) beg_bal
            FROM ap.ap_checks_all ac, apps.po_vendors pv, common_data cd
           WHERE ac.vendor_id = pv.vendor_id
             AND cd.entity_code = 'AP_PAYMENTS'
             AND cd.source_id_int_1 = ac.check_id
             AND nvl(ac.org_id, 81) = 81
             AND cd.effective_period_num < 20240001) t
   GROUP BY t.vendor_name, t.vendor_num, t.segment3, t.segment8),
--日记账数据
gje_net AS
/*--日记账发生额数据--*/
 (SELECT gcc.segment3,
         gcc.segment8,
         SUM(nvl(gjl.accounted_dr, 0)) account_dr,
         SUM(nvl(gjl.accounted_cr, 0)) account_cr
    FROM gl.gl_je_headers        gjh,
         gl.gl_je_lines          gjl,
         gl.gl_period_statuses   gps,
         gl.gl_code_combinations gcc
   WHERE gjh.je_header_id = gjl.je_header_id
     AND gjh.ledger_id = gps.ledger_id
     AND gjh.period_name = gps.period_name
     AND gps.application_id = 101
     AND gjl.code_combination_id = gcc.code_combination_id
     AND gjh.status = 'P'
     AND gjh.je_source <> 'Payables'
     AND gjh.ledger_id = 2021
     AND gps.effective_period_num BETWEEN 20240001 AND 20240001
     AND gcc.segment1 = '0010'
     AND (gcc.segment3 LIKE '203%' OR
         gcc.segment3 IN ('1150000', '2090100', '1190100', '1160000'))
   GROUP BY gcc.segment3, gcc.segment8),
je_begin AS
/*--日记账期初余额*/
 (SELECT gcc.segment3,
         gcc.segment8,
         SUM(nvl(gjl.accounted_dr, 0) - nvl(gjl.accounted_cr, 0)) begin_bal
    FROM gl.gl_je_headers        gjh,
         gl.gl_je_lines          gjl,
         gl.gl_period_statuses   gps,
         gl.gl_code_combinations gcc
   WHERE gjh.je_header_id = gjl.je_header_id
     AND gjh.ledger_id = gps.ledger_id
     AND gjh.period_name = gps.period_name
     AND gps.application_id = 101
     AND gjl.code_combination_id = gcc.code_combination_id
     AND gjh.status = 'P'
     AND gjh.je_source <> 'Payables'
     AND gjh.ledger_id = 2021
     AND gps.effective_period_num < 20240001
     AND gcc.segment1 = '0010'
     AND (gcc.segment3 LIKE '203%' OR
         gcc.segment3 IN ('1150000', '2090100', '1190100', '1160000'))
   GROUP BY gcc.segment3, gcc.segment8)
--均使用全外连接关联数据
--子模块
SELECT coalesce(sn.segment3, sb.segment3) segment3,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 3,
                                             x_seg_val => coalesce(sn.segment3,
                                                                   sb.segment3)) segment3_desc,
       coalesce(sn.segment8, sb.segment8) segment8,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 8,
                                             x_seg_val => coalesce(sn.segment8,
                                                                   sb.segment8)) segment8_desc,
       coalesce(sn.vendor_num, sb.vendor_num) vendor_num,
       coalesce(sn.vendor_name, sb.vendor_name) vendor_name,
       'CNY' currency_code,
       SUM(nvl(sb.begin_bal, 0)) begin_bal,
       SUM(nvl(sn.net_dr, 0)) net_dr,
       SUM(nvl(sn.net_cr, 0)) net_cr,
       SUM(nvl(sb.begin_bal, 0) + nvl(sn.net_dr, 0) - nvl(sn.net_cr, 0)) end_bal
  FROM source_net sn
  FULL OUTER JOIN source_begin sb
    ON sn.segment3 = sb.segment3
   AND sn.segment8 = sb.segment8
   AND sn.vendor_num = sb.vendor_num
 GROUP BY coalesce(sn.segment3, sb.segment3),
          coalesce(sn.segment8, sb.segment8),
          coalesce(sn.vendor_num, sb.vendor_num),
          coalesce(sn.vendor_name, sb.vendor_name)
UNION ALL
--GL 模块
SELECT coalesce(jn.segment3, jb.segment3) segment3,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 3,
                                             x_seg_val => coalesce(jn.segment3,
                                                                   jb.segment3)) segment3_desc,
       coalesce(jn.segment8, jb.segment8) segment8,
       gl_flexfields_pkg.get_description_sql(x_coa_id  => 50352,
                                             x_seg_num => 8,
                                             x_seg_val => coalesce(jn.segment8,
                                                                   jb.segment8)) segment8_desc,
       NULL AS vendor_num,
       NULL AS vendor_name,
       'CNY' currency_code,
       SUM(nvl(jb.begin_bal, 0)) begin_bal,
       SUM(nvl(jn.account_dr, 0)) account_dr,
       SUM(nvl(jn.account_cr, 0)) account_cr,
       SUM(nvl(jb.begin_bal, 0) + nvl(jn.account_dr, 0) -
           nvl(jn.account_cr, 0)) end_bal
  FROM gje_net jn
  FULL OUTER JOIN je_begin jb
    ON jn.segment3 = jb.segment3
 AND jn.segment8 = jb.segment8
 GROUP BY coalesce(jn.segment3, jb.segment3),
          coalesce(jn.segment8, jb.segment8)
 ORDER BY segment3, segment8, vendor_num;

  将代码转换部署为EBS系统中的并发请求,运行请求输出对应的数据结果文件,与财务人员提供的对比数据进行核对,完美对上!!!   最后,也是完整的解决了财务的需求内容。

+++==========================================================================+++
以上内容仅为个人学习记录使用。
如有转载,请附有原文出处链接。

posted on 2025-04-03 10:45  Hy旧人伤  阅读(104)  评论(0)    收藏  举报