Oracle Absence Management Tables & Configuration Guide

Oracle Fusion HCM's Absence Management module provides comprehensive leave and time-off tracking capabilities. Understanding the underlying database structure is essential for HR analysts, developers, and consultants who need to create custom reports, integrate with external systems, or troubleshoot absence-related issues.

This comprehensive guide covers the core absence management tables, their relationships, configuration patterns, and practical SQL examples for common absence tracking scenarios. From simple vacation balance queries to complex accrual calculations, you'll learn how to leverage Oracle's absence data model effectively.

Absence Management Data Model Overview

Oracle's Absence Management follows a hierarchical data model that supports complex leave policies, accrual rules, and approval workflows. The core concept revolves around absence plans that define leave types, entitlements that grant employees access to leave, and absence records that track actual time off.

Absence Plan
Leave policy
→
Entitlement
Employee allocation
→
Accrual
Balance calculation
→
Absence
Time off request

This model supports various absence scenarios including vacation, sick leave, personal time, sabbaticals, and complex regional leave types mandated by local legislation.

Core Absence Tables

ANC_ABSENCE_PLANS - Absence Plan Configuration

The ANC_ABSENCE_PLANS table defines leave policies and their associated rules. This is where absence types, accrual methods, carryover rules, and plan parameters are configured.

Key Columns Description Usage
ABSENCE_PLAN_ID Unique plan identifier Primary key, links to entitlements
PLAN_NAME Leave plan name (e.g., "Annual Leave") User-friendly identification
ABSENCE_TYPE_CODE Type classification (VACATION, SICK, etc.) Categorization for reporting
PLAN_UOM Unit of measure (Days, Hours) Calculation basis
ACCRUAL_METHOD How leave accrues (Annual, Monthly, etc.) Balance calculation rules
CARRYOVER_LIMIT Maximum carryover to next period Year-end processing
NEGATIVE_BALANCE_ALLOWED Allow negative balances Advance leave policy
APPROVAL_REQUIRED Requires manager approval Workflow configuration
EFFECTIVE_START_DATE Plan effective start date Date-effective tracking
EFFECTIVE_END_DATE Plan effective end date Date-effective tracking

Sample Query: Active Absence Plans

-- Get all active absence plans with their configuration
SELECT 
    ap.PLAN_NAME,
    ap.ABSENCE_TYPE_CODE,
    ap.PLAN_UOM,
    ap.ACCRUAL_METHOD,
    ap.CARRYOVER_LIMIT,
    CASE WHEN ap.NEGATIVE_BALANCE_ALLOWED = 'Y' 
         THEN 'Yes' ELSE 'No' END as ALLOWS_NEGATIVE_BALANCE,
    CASE WHEN ap.APPROVAL_REQUIRED = 'Y' 
         THEN 'Yes' ELSE 'No' END as REQUIRES_APPROVAL,
    ap.EFFECTIVE_START_DATE,
    ap.EFFECTIVE_END_DATE
FROM ANC_ABSENCE_PLANS ap
WHERE TRUNC(SYSDATE) BETWEEN ap.EFFECTIVE_START_DATE 
                          AND NVL(ap.EFFECTIVE_END_DATE, TO_DATE('4712-12-31', 'YYYY-MM-DD'))
ORDER BY ap.ABSENCE_TYPE_CODE, ap.PLAN_NAME;

ANC_PER_ABSENCE_ENTITLEMENTS - Employee Entitlements

This table links employees to absence plans and defines their specific entitlements, including annual allocations, start dates, and plan-specific parameters.

Key Columns Description Usage
ENTITLEMENT_ID Unique entitlement identifier Primary key
PERSON_ID Employee identifier Links to PER_ALL_PEOPLE_F
ABSENCE_PLAN_ID Links to absence plan Foreign key to ANC_ABSENCE_PLANS
START_DATE When entitlement begins Eligibility tracking
END_DATE When entitlement ends Eligibility tracking
ANNUAL_ENTITLEMENT Total yearly allocation Balance calculations
ENTITLEMENT_UOM Unit of measure override Person-specific settings
PRORATION_METHOD How to prorate partial periods Mid-year adjustments
CALCULATION_BASIS Basis for accrual calculation Payroll integration

Sample Query: Employee Entitlements Summary

-- Employee entitlements with plan details
SELECT 
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PLAN_NAME,
    ap.ABSENCE_TYPE_CODE,
    e.ANNUAL_ENTITLEMENT,
    ap.PLAN_UOM,
    e.START_DATE,
    e.END_DATE,
    CASE WHEN e.END_DATE IS NULL OR e.END_DATE > TRUNC(SYSDATE) 
         THEN 'Active' ELSE 'Expired' END as ENTITLEMENT_STATUS
FROM ANC_PER_ABSENCE_ENTITLEMENTS e
JOIN PER_ALL_PEOPLE_F p 
  ON e.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
JOIN ANC_ABSENCE_PLANS ap 
  ON e.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
  AND TRUNC(SYSDATE) BETWEEN ap.EFFECTIVE_START_DATE 
                          AND NVL(ap.EFFECTIVE_END_DATE, TO_DATE('4712-12-31', 'YYYY-MM-DD'))
WHERE p.CURRENT_EMPLOYEE_FLAG = 'Y'
  AND (e.END_DATE IS NULL OR e.END_DATE >= TRUNC(SYSDATE))
ORDER BY p.PERSON_NUMBER, ap.ABSENCE_TYPE_CODE;

ANC_PER_ABS_ENTRIES - Absence Records

This table stores individual absence records - the actual time off requests and approvals. Each row represents a specific absence period with dates, duration, status, and approval information.

Key Columns Description Usage
ABSENCE_ATTENDANCE_ID Unique absence record ID Primary key
PERSON_ID Employee taking absence Links to PER_ALL_PEOPLE_F
ABSENCE_PLAN_ID Type of leave taken Foreign key to ANC_ABSENCE_PLANS
START_DATE First day of absence Leave period definition
END_DATE Last day of absence Leave period definition
DURATION Total leave duration Balance impact calculation
DURATION_UOM Unit of measure (Days/Hours) Duration interpretation
APPROVAL_STATUS Current approval state Workflow tracking
APPROVED_BY Manager who approved Links to PER_ALL_PEOPLE_F
SUBMITTED_DATE When request was submitted Process timing
COMMENTS Absence reason/comments Documentation
ABSENCE_REASON_CODE Standardized reason code Reporting categorization

Sample Query: Recent Absence Requests

-- Recent absence requests with approval status
SELECT 
    p.PERSON_NUMBER,
    p.DISPLAY_NAME as EMPLOYEE_NAME,
    ap.PLAN_NAME,
    ae.START_DATE,
    ae.END_DATE,
    ae.DURATION,
    ae.DURATION_UOM,
    ae.APPROVAL_STATUS,
    mgr.DISPLAY_NAME as APPROVED_BY,
    ae.SUBMITTED_DATE,
    ae.COMMENTS
FROM ANC_PER_ABS_ENTRIES ae
JOIN PER_ALL_PEOPLE_F p 
  ON ae.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
JOIN ANC_ABSENCE_PLANS ap 
  ON ae.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
LEFT JOIN PER_ALL_PEOPLE_F mgr 
  ON ae.APPROVED_BY = mgr.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN mgr.EFFECTIVE_START_DATE 
                          AND mgr.EFFECTIVE_END_DATE
WHERE ae.SUBMITTED_DATE >= TRUNC(SYSDATE) - 30  -- Last 30 days
ORDER BY ae.SUBMITTED_DATE DESC;

ANC_PER_ABSENCE_ENTRIES - Balance Transactions

This table tracks all balance movements including accruals, deductions, adjustments, and carryovers. It provides a complete audit trail of how absence balances change over time.

Key Columns Description Usage
ABSENCE_ENTRY_ID Unique transaction identifier Primary key
PERSON_ID Employee affected Links to PER_ALL_PEOPLE_F
ABSENCE_PLAN_ID Leave plan affected Foreign key to ANC_ABSENCE_PLANS
TRANSACTION_TYPE Type of balance change ACCRUAL, DEDUCTION, ADJUSTMENT, CARRYOVER
TRANSACTION_DATE When change occurred Chronological tracking
QUANTITY Amount of change Balance calculation
UNIT_OF_MEASURE Days, hours, etc. Quantity interpretation
RUNNING_BALANCE Balance after this transaction Current balance tracking
SOURCE_REFERENCE Reference to source record Audit trail
COMMENTS Transaction description Explanation

Sample Query: Balance Movement History

-- Employee balance movement history
SELECT 
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PLAN_NAME,
    ae.TRANSACTION_DATE,
    ae.TRANSACTION_TYPE,
    ae.QUANTITY,
    ae.UNIT_OF_MEASURE,
    ae.RUNNING_BALANCE,
    ae.COMMENTS
FROM ANC_PER_ABSENCE_ENTRIES ae
JOIN PER_ALL_PEOPLE_F p 
  ON ae.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
JOIN ANC_ABSENCE_PLANS ap 
  ON ae.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
WHERE p.PERSON_NUMBER = :employee_number  -- Specific employee
  AND ae.TRANSACTION_DATE >= TRUNC(SYSDATE, 'YYYY')  -- Current year
ORDER BY ae.TRANSACTION_DATE DESC, ae.ABSENCE_ENTRY_ID DESC;

Key Configuration Tables

ANC_ACCRUAL_PLANS - Accrual Configuration

Accrual plans define how leave balances accumulate over time. This includes accrual rates, frequencies, and calculation rules.

Key Columns Description Configuration Impact
ACCRUAL_PLAN_ID Unique accrual plan identifier Links to absence plans
ACCRUAL_RATE Rate of accrual per period Calculation basis
ACCRUAL_FREQUENCY How often accrual occurs MONTHLY, WEEKLY, DAILY, etc.
MAXIMUM_ACCRUAL Cap on total accrued balance Use-it-or-lose-it policies
PRORATION_RULE How to handle partial periods Mid-period start/termination
WAITING_PERIOD Service time before eligibility New hire restrictions

ANC_ABSENCE_CALENDARS - Working Calendar Integration

This table manages the relationship between absence plans and working calendars, defining which days count as working days for absence calculations.

Key Columns Description Usage
ABSENCE_PLAN_ID Links to absence plan Plan-specific calendar rules
CALENDAR_ID Working calendar identifier Links to HXT_WORKING_TIME_CALENDARS
INCLUDE_HOLIDAYS Count holidays as absence Duration calculation rules
INCLUDE_WEEKENDS Count weekends as absence Duration calculation rules

Common Absence Management Queries

Employee Balance Summary

One of the most common requirements is to show current absence balances for employees:

-- Current absence balances for all active employees
WITH current_balances AS (
    SELECT 
        ae.PERSON_ID,
        ae.ABSENCE_PLAN_ID,
        ae.RUNNING_BALANCE
    FROM ANC_PER_ABSENCE_ENTRIES ae
    INNER JOIN (
        SELECT 
            PERSON_ID,
            ABSENCE_PLAN_ID,
            MAX(TRANSACTION_DATE) as MAX_TRANSACTION_DATE
        FROM ANC_PER_ABSENCE_ENTRIES
        GROUP BY PERSON_ID, ABSENCE_PLAN_ID
    ) latest ON ae.PERSON_ID = latest.PERSON_ID
                AND ae.ABSENCE_PLAN_ID = latest.ABSENCE_PLAN_ID
                AND ae.TRANSACTION_DATE = latest.MAX_TRANSACTION_DATE
)
SELECT 
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PLAN_NAME,
    ap.ABSENCE_TYPE_CODE,
    ent.ANNUAL_ENTITLEMENT,
    NVL(cb.RUNNING_BALANCE, 0) as CURRENT_BALANCE,
    ap.PLAN_UOM,
    CASE 
        WHEN NVL(cb.RUNNING_BALANCE, 0) < 0 THEN 'Negative'
        WHEN NVL(cb.RUNNING_BALANCE, 0) = 0 THEN 'Zero'
        WHEN NVL(cb.RUNNING_BALANCE, 0) > ent.ANNUAL_ENTITLEMENT THEN 'Over Entitlement'
        ELSE 'Normal'
    END as BALANCE_STATUS
FROM PER_ALL_PEOPLE_F p
JOIN ANC_PER_ABSENCE_ENTITLEMENTS ent 
  ON p.PERSON_ID = ent.PERSON_ID
  AND (ent.END_DATE IS NULL OR ent.END_DATE >= TRUNC(SYSDATE))
JOIN ANC_ABSENCE_PLANS ap 
  ON ent.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
  AND TRUNC(SYSDATE) BETWEEN ap.EFFECTIVE_START_DATE 
                          AND NVL(ap.EFFECTIVE_END_DATE, TO_DATE('4712-12-31', 'YYYY-MM-DD'))
LEFT JOIN current_balances cb 
  ON p.PERSON_ID = cb.PERSON_ID 
  AND ent.ABSENCE_PLAN_ID = cb.ABSENCE_PLAN_ID
WHERE p.CURRENT_EMPLOYEE_FLAG = 'Y'
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
ORDER BY p.PERSON_NUMBER, ap.ABSENCE_TYPE_CODE;

Absence Usage Analytics

Analyzing absence patterns and usage trends:

-- Absence usage analysis by department and leave type
SELECT 
    org.NAME as DEPARTMENT,
    ap.PLAN_NAME,
    ap.ABSENCE_TYPE_CODE,
    COUNT(ae.ABSENCE_ATTENDANCE_ID) as TOTAL_ABSENCES,
    SUM(ae.DURATION) as TOTAL_DAYS_TAKEN,
    AVG(ae.DURATION) as AVERAGE_ABSENCE_LENGTH,
    COUNT(DISTINCT ae.PERSON_ID) as EMPLOYEES_USING_LEAVE,
    ROUND(AVG(ae.DURATION), 2) as AVG_DURATION
FROM ANC_PER_ABS_ENTRIES ae
JOIN PER_ALL_PEOPLE_F p 
  ON ae.PERSON_ID = p.PERSON_ID
  AND ae.START_DATE BETWEEN p.EFFECTIVE_START_DATE 
                         AND p.EFFECTIVE_END_DATE
JOIN PER_ALL_ASSIGNMENTS_F a 
  ON p.PERSON_ID = a.PERSON_ID
  AND ae.START_DATE BETWEEN a.EFFECTIVE_START_DATE 
                         AND a.EFFECTIVE_END_DATE
  AND a.PRIMARY_FLAG = 'Y'
JOIN HR_ALL_ORGANIZATION_UNITS org 
  ON a.ORGANIZATION_ID = org.ORGANIZATION_ID
JOIN ANC_ABSENCE_PLANS ap 
  ON ae.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
WHERE ae.APPROVAL_STATUS = 'APPROVED'
  AND ae.START_DATE >= TRUNC(SYSDATE, 'YYYY')  -- Current year
  AND ae.DURATION_UOM = 'Days'
GROUP BY org.NAME, ap.PLAN_NAME, ap.ABSENCE_TYPE_CODE
HAVING COUNT(ae.ABSENCE_ATTENDANCE_ID) >= 3  -- Minimum sample size
ORDER BY org.NAME, TOTAL_DAYS_TAKEN DESC;

Pending Approvals Report

Critical for managers to track requests requiring approval:

-- Pending absence approvals by manager
SELECT 
    mgr.DISPLAY_NAME as MANAGER,
    COUNT(*) as PENDING_REQUESTS,
    MIN(ae.SUBMITTED_DATE) as OLDEST_REQUEST,
    MAX(ae.SUBMITTED_DATE) as NEWEST_REQUEST,
    SUM(ae.DURATION) as TOTAL_DAYS_PENDING
FROM ANC_PER_ABS_ENTRIES ae
JOIN PER_ALL_PEOPLE_F emp 
  ON ae.PERSON_ID = emp.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN emp.EFFECTIVE_START_DATE 
                          AND emp.EFFECTIVE_END_DATE
JOIN PER_ALL_ASSIGNMENTS_F a 
  ON emp.PERSON_ID = a.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN a.EFFECTIVE_START_DATE 
                          AND a.EFFECTIVE_END_DATE
  AND a.PRIMARY_FLAG = 'Y'
JOIN PER_ALL_PEOPLE_F mgr 
  ON a.MANAGER_ID = mgr.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN mgr.EFFECTIVE_START_DATE 
                          AND mgr.EFFECTIVE_END_DATE
WHERE ae.APPROVAL_STATUS IN ('PENDING', 'SUBMITTED')
GROUP BY mgr.PERSON_ID, mgr.DISPLAY_NAME
ORDER BY PENDING_REQUESTS DESC;

Advanced Configuration Scenarios

Complex Accrual Rules

Oracle Absence Management supports sophisticated accrual patterns. Here's how to query employees with different accrual rates based on service length:

-- Accrual rates based on years of service
WITH service_years AS (
    SELECT 
        p.PERSON_ID,
        p.PERSON_NUMBER,
        p.DISPLAY_NAME,
        wr.START_DATE,
        FLOOR(MONTHS_BETWEEN(TRUNC(SYSDATE), wr.START_DATE) / 12) as YEARS_OF_SERVICE
    FROM PER_ALL_PEOPLE_F p
    JOIN PER_WORK_RELATIONSHIPS wr 
      ON p.PERSON_ID = wr.PERSON_ID
      AND wr.PRIMARY_FLAG = 'Y'
      AND wr.TERMINATION_DATE IS NULL
    WHERE p.CURRENT_EMPLOYEE_FLAG = 'Y'
      AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                              AND p.EFFECTIVE_END_DATE
)
SELECT 
    sy.PERSON_NUMBER,
    sy.DISPLAY_NAME,
    sy.YEARS_OF_SERVICE,
    ap.PLAN_NAME,
    ent.ANNUAL_ENTITLEMENT,
    CASE 
        WHEN sy.YEARS_OF_SERVICE < 1 THEN 'Probationary (10 days)'
        WHEN sy.YEARS_OF_SERVICE < 5 THEN 'Standard (15 days)'
        WHEN sy.YEARS_OF_SERVICE < 10 THEN 'Senior (20 days)'
        ELSE 'Veteran (25 days)'
    END as SERVICE_TIER
FROM service_years sy
JOIN ANC_PER_ABSENCE_ENTITLEMENTS ent 
  ON sy.PERSON_ID = ent.PERSON_ID
  AND (ent.END_DATE IS NULL OR ent.END_DATE >= TRUNC(SYSDATE))
JOIN ANC_ABSENCE_PLANS ap 
  ON ent.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
  AND ap.ABSENCE_TYPE_CODE = 'VACATION'
ORDER BY sy.YEARS_OF_SERVICE, sy.PERSON_NUMBER;

Year-End Carryover Processing

Managing year-end carryover is a critical process. Here's how to identify employees with carryover scenarios:

-- Year-end carryover analysis
WITH current_balances AS (
    SELECT 
        ae.PERSON_ID,
        ae.ABSENCE_PLAN_ID,
        ae.RUNNING_BALANCE
    FROM ANC_PER_ABSENCE_ENTRIES ae
    INNER JOIN (
        SELECT 
            PERSON_ID,
            ABSENCE_PLAN_ID,
            MAX(TRANSACTION_DATE) as MAX_DATE
        FROM ANC_PER_ABSENCE_ENTRIES
        WHERE TRANSACTION_DATE <= TO_DATE('31-DEC-' || TO_CHAR(SYSDATE, 'YYYY'), 'DD-MON-YYYY')
        GROUP BY PERSON_ID, ABSENCE_PLAN_ID
    ) latest ON ae.PERSON_ID = latest.PERSON_ID
                AND ae.ABSENCE_PLAN_ID = latest.ABSENCE_PLAN_ID
                AND ae.TRANSACTION_DATE = latest.MAX_DATE
)
SELECT 
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PLAN_NAME,
    cb.RUNNING_BALANCE as YEAR_END_BALANCE,
    ap.CARRYOVER_LIMIT,
    CASE 
        WHEN cb.RUNNING_BALANCE <= ap.CARRYOVER_LIMIT THEN cb.RUNNING_BALANCE
        ELSE ap.CARRYOVER_LIMIT
    END as CARRYOVER_AMOUNT,
    CASE 
        WHEN cb.RUNNING_BALANCE > ap.CARRYOVER_LIMIT 
        THEN cb.RUNNING_BALANCE - ap.CARRYOVER_LIMIT
        ELSE 0
    END as FORFEIT_AMOUNT
FROM current_balances cb
JOIN PER_ALL_PEOPLE_F p 
  ON cb.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
JOIN ANC_ABSENCE_PLANS ap 
  ON cb.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
WHERE p.CURRENT_EMPLOYEE_FLAG = 'Y'
  AND ap.CARRYOVER_LIMIT > 0
  AND cb.RUNNING_BALANCE > 0
ORDER BY FORFEIT_AMOUNT DESC;

Integration and Data Quality Considerations

Data Validation Queries

Ensuring data integrity in absence management is crucial for accurate reporting and compliance:

-- Data quality checks for absence management
-- Check 1: Employees without entitlements
SELECT 
    'Employees without vacation entitlements' as ISSUE,
    COUNT(*) as ISSUE_COUNT
FROM PER_ALL_PEOPLE_F p
WHERE p.CURRENT_EMPLOYEE_FLAG = 'Y'
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE 
                          AND p.EFFECTIVE_END_DATE
  AND NOT EXISTS (
      SELECT 1 FROM ANC_PER_ABSENCE_ENTITLEMENTS e
      JOIN ANC_ABSENCE_PLANS ap ON e.ABSENCE_PLAN_ID = ap.ABSENCE_PLAN_ID
      WHERE e.PERSON_ID = p.PERSON_ID
        AND ap.ABSENCE_TYPE_CODE = 'VACATION'
        AND (e.END_DATE IS NULL OR e.END_DATE >= TRUNC(SYSDATE))
  )

UNION ALL

-- Check 2: Absences without corresponding entitlements  
SELECT 
    'Absences without entitlements',
    COUNT(*)
FROM ANC_PER_ABS_ENTRIES ae
WHERE NOT EXISTS (
    SELECT 1 FROM ANC_PER_ABSENCE_ENTITLEMENTS e
    WHERE e.PERSON_ID = ae.PERSON_ID
      AND e.ABSENCE_PLAN_ID = ae.ABSENCE_PLAN_ID
      AND ae.START_DATE BETWEEN e.START_DATE 
                            AND NVL(e.END_DATE, TO_DATE('4712-12-31', 'YYYY-MM-DD'))
  )

UNION ALL

-- Check 3: Overlapping absence periods
SELECT 
    'Overlapping absence periods',
    COUNT(*)
FROM ANC_PER_ABS_ENTRIES a1
WHERE EXISTS (
    SELECT 1 FROM ANC_PER_ABS_ENTRIES a2
    WHERE a1.PERSON_ID = a2.PERSON_ID
      AND a1.ABSENCE_ATTENDANCE_ID != a2.ABSENCE_ATTENDANCE_ID
      AND a1.APPROVAL_STATUS = 'APPROVED'
      AND a2.APPROVAL_STATUS = 'APPROVED'
      AND (a1.START_DATE BETWEEN a2.START_DATE AND a2.END_DATE
           OR a1.END_DATE BETWEEN a2.START_DATE AND a2.END_DATE
           OR (a1.START_DATE <= a2.START_DATE AND a1.END_DATE >= a2.END_DATE))
  );

Performance Optimization

Performance Tips: Absence tables can grow large over time. Always include date filters in your queries, especially when looking at historical data. Consider partitioning strategies for large deployments and use appropriate indexes on PERSON_ID, ABSENCE_PLAN_ID, and date columns.

Security Considerations

Data Security: Absence data contains sensitive employee information including medical leave details. Ensure your queries respect Oracle's data security framework and only expose data that users are authorized to see. Consider using VPD (Virtual Private Database) policies where appropriate.

Best Practices for Absence Management Reporting

1. Establish Clear Metrics

2. Regular Data Maintenance

-- Monthly data maintenance checklist query
SELECT 
    CHECK_TYPE,
    RESULT_COUNT,
    CASE WHEN RESULT_COUNT > 0 THEN 'Action Required' ELSE 'OK' END as STATUS
FROM (
    SELECT 'Expired Entitlements Not Closed' as CHECK_TYPE,
           COUNT(*) as RESULT_COUNT
    FROM ANC_PER_ABSENCE_ENTITLEMENTS 
    WHERE END_DATE < TRUNC(SYSDATE) - 90
      AND END_DATE IS NOT NULL
      
    UNION ALL
    
    SELECT 'Future-Dated Approved Absences',
           COUNT(*)
    FROM ANC_PER_ABS_ENTRIES 
    WHERE APPROVAL_STATUS = 'APPROVED'
      AND START_DATE > ADD_MONTHS(TRUNC(SYSDATE), 12)
      
    UNION ALL
    
    SELECT 'Long Pending Approvals',
           COUNT(*)
    FROM ANC_PER_ABS_ENTRIES 
    WHERE APPROVAL_STATUS IN ('PENDING', 'SUBMITTED')
      AND SUBMITTED_DATE < TRUNC(SYSDATE) - 30
);

3. Automated Monitoring

Set up automated monitoring for:

Mastering Oracle's Absence Management tables enables sophisticated leave tracking, compliance reporting, and workforce analytics. The hierarchical model supports complex business rules while maintaining data integrity and auditability.

Whether you're implementing new absence policies, troubleshooting balance issues, or building comprehensive absence analytics, understanding these core tables and their relationships is essential. Combine absence data with core HCM entities for comprehensive workforce reporting, and leverage REST APIs for real-time integrations with time tracking and payroll systems.

Remember that absence management directly impacts payroll calculations and should be integrated with your broader HCM reporting strategy for maximum effectiveness.