Blog / Finance
Finance

Oracle Fusion Finance SQL Guide: 18 Practical Queries for GL, AP, AR, and SLA Reporting

May 27, 2026 20 min read
Back to Blog

Oracle Fusion Finance stores transactional and accounting data across a large set of interconnected tables spanning General Ledger (GL), Accounts Payable (AP), Accounts Receivable (AR), Subledger Accounting (SLA), Cash Management, and Procurement integrations.

For reporting teams, BI developers, OTBI analysts, and Oracle Fusion consultants, understanding the underlying Finance SQL structure is essential for building reliable reports, reconciling balances, troubleshooting discrepancies, and validating OTBI or BI Publisher outputs.

This guide provides 18 practical Oracle Fusion Finance SQL queries illustrating commonly used join paths and reporting patterns - including ledger filters, currency handling, and performance considerations - covering:

  • General Ledger journals and period balances
  • Trial balance and YTD account activity
  • AP invoice and payment reporting
  • Supplier spend analysis
  • AR aging and customer balances
  • Period reconciliation patterns
  • Cross-module AP-to-GL tracing via Subledger Accounting
  • Cash management and bank account visibility
  • BI Publisher-ready reporting SQL

Core Oracle Fusion Finance Tables

Table Module Contains
GL_JE_HEADERSGLJournal entry headers
GL_JE_LINESGLJournal entry lines
GL_CODE_COMBINATIONSGLChart of accounts combinations
GL_BALANCESGLPeriod balances
GL_PERIODSGLAccounting periods
XLA_AE_HEADERSSLASubledger accounting event headers
XLA_AE_LINESSLASubledger accounting journal lines
AP_INVOICES_ALLAPSupplier invoice headers
AP_INVOICE_LINES_ALLAPSupplier invoice lines
AP_INVOICE_DISTRIBUTIONS_ALLAPInvoice accounting distributions
AP_SUPPLIERSAPSupplier master
AP_CHECKS_ALLAPPayments and checks
AR_PAYMENT_SCHEDULES_ALLARAR due dates and outstanding balances
RA_CUSTOMER_TRX_ALLARAR invoice and transaction headers
HZ_CUST_ACCOUNTSARCustomer accounts
HZ_PARTIESARCustomer names and party data
CE_BANK_ACCOUNTSCashBank account definitions
XLA_TRANSACTION_ENTITIESSLALinks subledger events to source transaction records (AP, AR, Assets)
GL_IMPORT_REFERENCESSLA / GLLinks SLA accounting lines to GL journal lines - key for AP-to-GL traces
XLA_DISTRIBUTION_LINKSSLALinks SLA accounting entries to source transaction distributions

Finance Reporting Architecture: Ledger, Data Access Set, and Org Structure

Before writing Oracle Fusion Finance SQL, understanding the reporting hierarchy is essential. Every GL query must be scoped to a Ledger - and what a given user can see depends on their assigned Data Access Set. The same query can return different results across users, environments, and legal entities.

Concept What it defines SQL impact
Ledger A single accounting book with a calendar, chart of accounts, and ledger currency Always filter GL_JE_HEADERS, GL_BALANCES, and GL_PERIOD_STATUSES by ledger_id
Ledger Set A named group of ledgers - allows cross-ledger reporting in a single OTBI or SQL query Queries spanning a Ledger Set may return multi-currency results; always check currency_code filters
Data Access Set Defines which ledgers and balancing segments a Finance user can access in reports Two Finance users running the same GL query may see different journals depending on their assigned Data Access Set
Primary Ledger The main accounting ledger - transactions are always posted here first Standard GL, AP, and AR reporting targets the primary ledger; filter by ledger_id of the primary
Secondary Ledger A parallel ledger using a different chart of accounts, currency, or accounting method (e.g. IFRS vs local GAAP) Queries must explicitly filter by the secondary ledger_id; mixing primary and secondary entries produces incorrect results

Always pass ledger_id as a bind variable or explicit filter in every GL query. GL_JE_HEADERS, GL_BALANCES, and GL_PERIOD_STATUSES are multi-ledger tables - omitting the ledger filter causes queries to aggregate across all ledgers, producing incorrect totals.

General Ledger SQL Queries

GL queries require careful attention to ledger scope, journal status, and currency type. The queries below cover the most common GL reporting scenarios: posted journals, period balances, trial balance, and period management.

Query 1 - Posted Journal Lines for a Period

Retrieve posted journal lines with account combinations and debit/credit values for a given ledger and period.

SELECT
    gjh.je_header_id,
    gjh.name                          AS journal_name,
    gjh.je_source,
    gjh.je_category,
    gjh.period_name,
    gjh.posted_date,
    gjl.je_line_num,
    gjl.effective_date,
    gcc.concatenated_segments         AS account_combination,
    gjl.entered_dr,
    gjl.entered_cr,
    gjl.accounted_dr,
    gjl.accounted_cr,
    gjl.description
FROM
    gl_je_headers              gjh
    JOIN gl_je_lines           gjl  ON gjl.je_header_id      = gjh.je_header_id
    JOIN gl_code_combinations  gcc  ON gcc.code_combination_id = gjl.code_combination_id
WHERE
    gjh.status      = 'P'
    AND gjh.ledger_id   = :p_ledger_id
    AND gjh.period_name = :p_period_name
ORDER BY
    gjh.posted_date,
    gjl.je_line_num;

Notes

  • status = 'P' limits to posted journals only - always include this filter
  • Always filter by ledger_id - GL tables are multi-ledger
  • accounted_dr/cr are ledger currency amounts; entered_dr/cr are transaction currency amounts

Query 2 - GL Account Balances by Period

GL_BALANCES holds pre-aggregated period net amounts. Use this for fast balance reporting without summarising journal lines.

SELECT
    gb.period_name,
    gcc.concatenated_segments          AS account,
    gb.begin_balance_dr,
    gb.begin_balance_cr,
    gb.period_net_dr,
    gb.period_net_cr,
    (gb.begin_balance_dr - gb.begin_balance_cr
     + gb.period_net_dr  - gb.period_net_cr)  AS ending_balance
FROM
    gl_balances           gb
    JOIN gl_code_combinations gcc ON gcc.code_combination_id = gb.code_combination_id
WHERE
    gb.actual_flag  = 'A'
    AND gb.ledger_id    = :p_ledger_id
    AND gb.period_name  = :p_period_name
ORDER BY
    gcc.concatenated_segments;

Notes

  • actual_flag = 'A' = actual balances  |  'B' = budget  |  'E' = encumbrance
  • Far more performant than aggregating journal lines for period balance reports

Query 3 - Trial Balance (YTD)

Summarise all periods up to and including the selected period to produce a year-to-date trial balance.

SELECT
    gcc.concatenated_segments  AS account,
    SUM(gb.period_net_dr)      AS total_debits,
    SUM(gb.period_net_cr)      AS total_credits,
    SUM(gb.begin_balance_dr - gb.begin_balance_cr
        + gb.period_net_dr  - gb.period_net_cr)  AS ending_balance
FROM
    gl_balances           gb
    JOIN gl_code_combinations gcc ON gcc.code_combination_id = gb.code_combination_id
WHERE
    gb.ledger_id   = :p_ledger_id
    AND gb.actual_flag = 'A'
    AND gb.period_year = :p_year
    AND gb.period_num <= :p_period_num
GROUP BY
    gcc.concatenated_segments
ORDER BY
    gcc.concatenated_segments;

Notes

  • Filter by period_year + period_num <= :p_period_num to accumulate YTD balances
  • Add a currency_code filter if your ledger contains multiple currencies
  • Double-count risk: Depending on your ledger configuration, YTD balances may already be reflected in begin_balance values. Validate the accumulation logic against your specific ledger setup - in some configurations, querying multiple periods with this formula overstates the ending balance

Query 4 - Journals by Source and Category

Useful for audit trails and reconciliation - shows the volume and value of postings by journal source and category.

SELECT
    gjh.je_source,
    gjh.je_category,
    COUNT(*)                       AS journal_count,
    SUM(NVL(gjl.accounted_dr, 0))  AS total_dr,
    SUM(NVL(gjl.accounted_cr, 0))  AS total_cr
FROM
    gl_je_headers gjh
    JOIN gl_je_lines gjl ON gjl.je_header_id = gjh.je_header_id
WHERE
    gjh.status      = 'P'
    AND gjh.ledger_id   = :p_ledger_id
    AND gjh.period_name = :p_period_name
GROUP BY
    gjh.je_source,
    gjh.je_category
ORDER BY
    total_dr DESC;

Query 5 - Unposted Journals

Identify draft or incomplete journals that have not yet been posted to the ledger.

SELECT
    gjh.name,
    gjh.je_source,
    gjh.je_category,
    gjh.period_name,
    gjh.creation_date,
    gjh.status
FROM
    gl_je_headers gjh
WHERE
    gjh.ledger_id = :p_ledger_id
    AND gjh.status != 'P'
ORDER BY
    gjh.creation_date DESC;

Query 6 - GL Period Statuses

Returns accounting period statuses for the General Ledger application (application_id = 101). Useful before period-end close or when debugging posting errors. GL_PERIOD_STATUSES is application-scoped - other modules use separate period status records with different application_id values.

SELECT
    gp.period_name,
    gp.start_date,
    gp.end_date,
    gp.adjustment_period_flag,
    gp.closing_status
FROM
    gl_period_statuses gp
WHERE
    gp.ledger_id       = :p_ledger_id
    AND gp.application_id  = 101
ORDER BY
    gp.start_date DESC;

Accounts Payable SQL Queries

AP queries cover invoices, payments, aging, and supplier spend. The key join is AP_INVOICES_ALL to AP_SUPPLIERS via vendor_id. Always filter cancelled_date IS NULL to exclude voided invoices.

Note on AP_SUPPLIERS: Supplier master data in Oracle Fusion is built on top of the TCA (Trading Community Architecture) model. AP_SUPPLIERS remains the most common reporting entry point, but supplier attributes such as party names, classifications, and addresses may also need to be sourced from HZ_* tables depending on your reporting requirements. Depending on the Oracle Fusion release and security configuration, supplier information may also be exposed through POZ_SUPPLIERS views in some environments.

Query 7 - Open Supplier Invoices

Returns invoices that are unpaid or partially paid and not cancelled.

SELECT
    ai.invoice_num,
    ai.invoice_date,
    ai.invoice_amount,
    NVL(ai.amount_paid, 0)                       AS amount_paid,
    ai.invoice_amount - NVL(ai.amount_paid, 0)   AS outstanding_amount,
    ai.payment_status_flag,
    ai.due_date,
    s.vendor_name,
    s.segment1  AS supplier_number
FROM
    ap_invoices_all ai
    JOIN ap_suppliers s ON s.vendor_id = ai.vendor_id
WHERE
    ai.cancelled_date IS NULL
    AND ai.payment_status_flag IN ('N', 'P')
ORDER BY
    ai.due_date;

Notes

  • payment_status_flag: N = not paid  |  P = partially paid  |  Y = fully paid
  • Add AND ai.org_id = :p_org_id in multi-org environments

Query 8 - AP Aging Buckets

Groups outstanding AP balances by supplier into standard aging buckets.

SELECT
    s.vendor_name,
    SUM(CASE WHEN TRUNC(SYSDATE) - ai.due_date <= 0
             THEN ai.invoice_amount - NVL(ai.amount_paid, 0) ELSE 0 END)  AS current_bucket,
    SUM(CASE WHEN TRUNC(SYSDATE) - ai.due_date BETWEEN 1  AND 30
             THEN ai.invoice_amount - NVL(ai.amount_paid, 0) ELSE 0 END)  AS bucket_1_30,
    SUM(CASE WHEN TRUNC(SYSDATE) - ai.due_date BETWEEN 31 AND 60
             THEN ai.invoice_amount - NVL(ai.amount_paid, 0) ELSE 0 END)  AS bucket_31_60,
    SUM(CASE WHEN TRUNC(SYSDATE) - ai.due_date > 60
             THEN ai.invoice_amount - NVL(ai.amount_paid, 0) ELSE 0 END)  AS over_60
FROM
    ap_invoices_all ai
    JOIN ap_suppliers s ON s.vendor_id = ai.vendor_id
WHERE
    ai.cancelled_date IS NULL
GROUP BY
    s.vendor_name
ORDER BY
    over_60 DESC;

Query 9 - AP Spend by Supplier (Rolling 12 Months)

SELECT
    s.vendor_name,
    COUNT(ai.invoice_id)        AS invoice_count,
    SUM(ai.invoice_amount)      AS total_invoiced,
    SUM(NVL(ai.amount_paid, 0)) AS total_paid
FROM
    ap_invoices_all ai
    JOIN ap_suppliers s ON s.vendor_id = ai.vendor_id
WHERE
    ai.invoice_date >= ADD_MONTHS(TRUNC(SYSDATE), -12)
    AND ai.cancelled_date IS NULL
GROUP BY
    s.vendor_name
ORDER BY
    total_invoiced DESC;

Query 10 - PO-Matched AP Invoices

Links AP invoices to their purchase orders via the invoice line table.

SELECT
    ai.invoice_num,
    ai.invoice_date,
    ai.invoice_amount,
    ph.segment1   AS po_number,
    s.vendor_name
FROM
    ap_invoices_all      ai
    JOIN ap_invoice_lines_all ail ON ail.invoice_id   = ai.invoice_id
    JOIN po_headers_all   ph  ON ph.po_header_id  = ail.po_header_id
    JOIN ap_suppliers     s   ON s.vendor_id      = ai.vendor_id
WHERE
    ail.po_header_id IS NOT NULL
    AND ai.cancelled_date IS NULL
ORDER BY
    ai.invoice_date DESC;

Query 11 - Invoice Distribution Accounting

Shows the GL accounts charged per invoice distribution line - useful for charge account reconciliation.

SELECT
    ai.invoice_num,
    aid.line_type_lookup_code,
    aid.amount,
    gcc.concatenated_segments  AS account
FROM
    ap_invoices_all              ai
    JOIN ap_invoice_distributions_all aid ON aid.invoice_id          = ai.invoice_id
    JOIN gl_code_combinations    gcc ON gcc.code_combination_id = aid.dist_code_combination_id
WHERE
    ai.cancelled_date IS NULL
ORDER BY
    ai.invoice_num,
    aid.distribution_line_number;

Query 12 - Payment History

Returns supplier payment records for the past six months. AP_CHECKS_ALL stores all payment records regardless of payment method - in modern Oracle Fusion implementations, most payments are electronic (EFT/ACH) rather than physical checks. The check_number column will still be populated for electronic payments, typically with the payment reference number.

SELECT
    ac.check_number,
    ac.check_date,
    ac.amount,
    ac.currency_code,
    ac.status_lookup_code,
    s.vendor_name
FROM
    ap_checks_all  ac
    JOIN ap_suppliers s ON s.vendor_id = ac.vendor_id
WHERE
    ac.check_date >= ADD_MONTHS(TRUNC(SYSDATE), -6)
ORDER BY
    ac.check_date DESC;

Accounts Receivable SQL Queries

AR data flows through AR_PAYMENT_SCHEDULES_ALL (outstanding balances) and RA_CUSTOMER_TRX_ALL (transaction headers). Customer identity is resolved via HZ_CUST_ACCOUNTS and HZ_PARTIES.

Query 13 - Outstanding AR Balances by Customer

Returns open AR balances aggregated by customer. Note: customer join paths in AR_PAYMENT_SCHEDULES_ALL can vary depending on transaction type and Oracle Fusion release. Validate the customer_id join column against your environment - some transaction types may use a different identifier.

SELECT
    hp.party_name,
    hca.account_number,
    SUM(aps.amount_due_remaining)  AS outstanding_balance
FROM
    ar_payment_schedules_all  aps
    JOIN hz_cust_accounts  hca ON hca.cust_account_id = aps.customer_id
    JOIN hz_parties        hp  ON hp.party_id         = hca.party_id
WHERE
    aps.status = 'OP'
GROUP BY
    hp.party_name,
    hca.account_number
ORDER BY
    outstanding_balance DESC;

Query 14 - AR Aging by Customer

SELECT
    hp.party_name,
    SUM(CASE WHEN TRUNC(SYSDATE) - aps.due_date BETWEEN 1  AND 30
             THEN aps.amount_due_remaining ELSE 0 END)  AS bucket_1_30,
    SUM(CASE WHEN TRUNC(SYSDATE) - aps.due_date BETWEEN 31 AND 60
             THEN aps.amount_due_remaining ELSE 0 END)  AS bucket_31_60,
    SUM(CASE WHEN TRUNC(SYSDATE) - aps.due_date > 60
             THEN aps.amount_due_remaining ELSE 0 END)  AS over_60
FROM
    ar_payment_schedules_all  aps
    JOIN hz_cust_accounts  hca ON hca.cust_account_id = aps.customer_id
    JOIN hz_parties        hp  ON hp.party_id         = hca.party_id
WHERE
    aps.status = 'OP'
GROUP BY
    hp.party_name
ORDER BY
    over_60 DESC;

Query 15 - Customer Invoice Activity

SELECT
    hp.party_name,
    rcta.trx_number,
    rcta.trx_date,
    rcta.invoice_currency_code,
    rcta.complete_flag
FROM
    ra_customer_trx_all  rcta
    JOIN hz_cust_accounts  hca ON hca.cust_account_id = rcta.bill_to_customer_id
    JOIN hz_parties        hp  ON hp.party_id         = hca.party_id
WHERE
    rcta.trx_date >= ADD_MONTHS(TRUNC(SYSDATE), -12)
ORDER BY
    rcta.trx_date DESC;

Subledger Accounting (SLA) Queries

Subledger Accounting (SLA) is the bridge between Oracle Fusion subledgers (AP, AR, Assets) and General Ledger. XLA_AE_HEADERS and XLA_AE_LINES hold the accounting entries before they are posted to GL_JE_LINES via GL_IMPORT_REFERENCES.

Important - SLA data model varies significantly by environment and release: The examples below illustrate the conceptual join path from AP through SLA into GL. Production implementations often require joining via XLA_TRANSACTION_ENTITIES and filtering by APPLICATION_ID and ENTITY_CODE. The direct entity_id = invoice_id join shown below may not resolve correctly in all environments. Always validate the join path in your specific Oracle Fusion instance before using in production reports.

Query 16 - AP Invoice to SLA Accounting

Links AP invoice records to their subledger accounting entries.

SELECT
    ai.invoice_num,
    xah.ae_header_id,
    xal.ae_line_num,
    xal.accounted_dr,
    xal.accounted_cr,
    gcc.concatenated_segments  AS account
FROM
    ap_invoices_all   ai
    JOIN xla_ae_headers  xah ON xah.entity_id     = ai.invoice_id
    JOIN xla_ae_lines    xal ON xal.ae_header_id  = xah.ae_header_id
    JOIN gl_code_combinations gcc
                             ON gcc.code_combination_id = xal.code_combination_id
WHERE
    ai.cancelled_date IS NULL
ORDER BY
    ai.invoice_num,
    xal.ae_line_num;

Query 17 - Trace AP Invoice into GL Journals

Full end-to-end trace from a specific AP invoice through SLA into the GL journal that was posted to the ledger.

SELECT
    ai.invoice_num,
    gjh.name                   AS journal_name,
    gjh.period_name,
    gjl.je_line_num,
    gcc.concatenated_segments  AS account,
    gjl.accounted_dr,
    gjl.accounted_cr
FROM
    ap_invoices_all    ai
    JOIN xla_ae_headers   xah ON xah.entity_id      = ai.invoice_id
    JOIN xla_ae_lines     xal ON xal.ae_header_id   = xah.ae_header_id
    JOIN gl_import_references gir
                              ON gir.gl_sl_link_id  = xal.gl_sl_link_id
    JOIN gl_je_lines      gjl ON gjl.je_header_id   = gir.je_header_id
                              AND gjl.je_line_num   = gir.je_line_num
    JOIN gl_je_headers    gjh ON gjh.je_header_id   = gjl.je_header_id
    JOIN gl_code_combinations gcc
                              ON gcc.code_combination_id = gjl.code_combination_id
WHERE
    ai.invoice_num = :p_invoice_num;

Cash Management Queries

Query 18 - Bank Account Usage by Legal Entity

Returns active bank accounts together with their usage assignments. CE_BANK_ACCT_USES_ALL links each bank account to the legal entities or business units it is assigned to - useful for cash management reconciliation and treasury reporting.

SELECT
    cba.bank_account_name,
    cba.bank_account_num,
    cba.currency_code,
    cbau.account_type,
    cbau.primary_acct_use_flag,
    cba.start_date,
    cba.end_date
FROM
    ce_bank_accounts          cba
    JOIN ce_bank_acct_uses_all cbau
        ON cbau.bank_account_id = cba.bank_account_id
WHERE
    (cba.end_date IS NULL OR cba.end_date >= TRUNC(SYSDATE))
ORDER BY
    cba.bank_account_name,
    cbau.account_type;

To include legal entity names, join CE_BANK_ACCT_USES_ALL to XLE_ENTITY_PROFILES via legal_entity_id. primary_acct_use_flag = 'Y' identifies the primary usage assignment for each bank account.

Security Note: Query results across these Finance tables may vary depending on the executing user's Oracle Fusion Data Roles, Data Access Sets, Business Unit assignments, and Ledger security configuration. Two Finance users running the same GL query may see different journals depending on their assigned Data Access Set and Ledger scope. For a detailed overview of how Oracle Fusion security affects SQL query results across GL, AP, and AR, see Oracle Fusion SQL Security Explained.

Common Oracle Fusion Finance SQL Mistakes

1 - Missing Ledger Filters

GL_JE_HEADERS, GL_BALANCES, and GL_PERIOD_STATUSES are multi-ledger tables. Omitting ledger_id returns data across all ledgers and produces incorrect aggregations.

2 - Mixing Entered and Accounted Currency

entered_dr/cr is the transaction currency amount. accounted_dr/cr is the ledger currency amount. Aggregating them together produces meaningless totals in multi-currency environments.

3 - Not Filtering by Posted Status

GL queries should always include gjh.status = 'P' unless you specifically need to see draft or unposted journals. Including unposted entries in balance or audit reports is a common cause of reconciliation discrepancies.

4 - Using AP Invoice Totals for Accounting Reconciliation

AP_INVOICES_ALL totals represent operational invoice amounts. For accounting reconciliation, use Subledger Accounting (XLA_*) tables or GL journal lines - not invoice headers, which may not reflect rounding, tax, or prepayment adjustments.

Bonus: BI Publisher Parameterized GL Journal Report

BI Publisher reports benefit from optional bind parameters so Finance users can filter by ledger, period, or account without the developer changing the SQL. The pattern below uses NVL to make each filter optional - passing NULL returns all rows for that dimension.

SELECT
    gjh.name            AS journal_name,
    gjh.je_source,
    gjh.je_category,
    gjh.period_name,
    gjh.currency_code,
    gjl.je_line_num,
    gcc.concatenated_segments  AS account,
    gjl.accounted_dr,
    gjl.accounted_cr,
    gjl.description
FROM
    gl_je_headers      gjh
    JOIN gl_je_lines   gjl ON gjl.je_header_id        = gjh.je_header_id
    JOIN gl_code_combinations gcc
                           ON gcc.code_combination_id = gjl.code_combination_id
WHERE
    gjh.status       = 'P'
    AND gjh.ledger_id    = NVL(:p_ledger_id,   gjh.ledger_id)
    AND gjh.period_name  = NVL(:p_period_name, gjh.period_name)
    AND gjh.je_source    = NVL(:p_je_source,   gjh.je_source)
    AND (:p_account_seg IS NULL
         OR gcc.concatenated_segments LIKE :p_account_seg || '%')
ORDER BY
    gjh.period_name,
    gjh.name,
    gjl.je_line_num;

Bind variable pattern: pass NULL to any parameter to return all values for that dimension. :p_ledger_id should always be populated in production to avoid cross-ledger aggregation. For account segment filtering, pass a prefix such as 6 to return all accounts starting with 6 (expense accounts in many chart-of-accounts configurations).

Accelerate Finance SQL Development with FusionLens SQL

📊
Finance Schema Navigator

Browse GL, AP, AR, and SLA tables with column descriptions and data types - no documentation hunting.

📋
BI Publisher Ready

Queries plug directly into BI Publisher data models for GL, AP, and AR financial reports and period-close outputs.

📤
One-Click Export

Export GL, AP, and AR results in one click - ready for period-close reconciliation, audit review, or Finance team distribution.

Final Thoughts

Oracle Fusion Finance reporting requires more than basic SQL knowledge. Understanding ledger structures, SLA accounting flows, cross-module joins, and the distinction between operational and accounting data is essential for building accurate financial reports.

The queries in this guide cover the most common Finance reporting scenarios - from straightforward GL balance reports through to cross-module traces linking an AP invoice all the way into a posted GL journal. Use them as a starting point and adapt the filters and columns to your specific ledger, org, and currency requirements.