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_HEADERS | GL | Journal entry headers |
| GL_JE_LINES | GL | Journal entry lines |
| GL_CODE_COMBINATIONS | GL | Chart of accounts combinations |
| GL_BALANCES | GL | Period balances |
| GL_PERIODS | GL | Accounting periods |
| XLA_AE_HEADERS | SLA | Subledger accounting event headers |
| XLA_AE_LINES | SLA | Subledger accounting journal lines |
| AP_INVOICES_ALL | AP | Supplier invoice headers |
| AP_INVOICE_LINES_ALL | AP | Supplier invoice lines |
| AP_INVOICE_DISTRIBUTIONS_ALL | AP | Invoice accounting distributions |
| AP_SUPPLIERS | AP | Supplier master |
| AP_CHECKS_ALL | AP | Payments and checks |
| AR_PAYMENT_SCHEDULES_ALL | AR | AR due dates and outstanding balances |
| RA_CUSTOMER_TRX_ALL | AR | AR invoice and transaction headers |
| HZ_CUST_ACCOUNTS | AR | Customer accounts |
| HZ_PARTIES | AR | Customer names and party data |
| CE_BANK_ACCOUNTS | Cash | Bank account definitions |
| XLA_TRANSACTION_ENTITIES | SLA | Links subledger events to source transaction records (AP, AR, Assets) |
| GL_IMPORT_REFERENCES | SLA / GL | Links SLA accounting lines to GL journal lines - key for AP-to-GL traces |
| XLA_DISTRIBUTION_LINKS | SLA | Links 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/crare ledger currency amounts;entered_dr/crare 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_numto accumulate YTD balances - Add a
currency_codefilter 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_idin 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
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.
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.
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.
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
Browse GL, AP, AR, and SLA tables with column descriptions and data types - no documentation hunting.
Queries plug directly into BI Publisher data models for GL, AP, and AR financial reports and period-close outputs.
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.