Oracle HCM Performance Management Tables Guide — Appraisals, Goals & Talent Review

Oracle Fusion HCM's Performance Management module powers talent reviews, goal tracking, and performance appraisals across your organization. Understanding the underlying database structure is essential for HR analysts, system administrators, and developers who need to create performance reports, track review cycles, or integrate performance data with external systems.

This guide covers the core performance management tables (HRA_* prefix), their relationships, and practical SQL examples for common performance scenarios. From active appraisal tracking to 360 feedback analysis and performance rating distributions, you'll learn how to leverage Oracle's performance data model effectively.

Why Performance Management Data Is Hard to Query

Performance management in Oracle HCM spans multiple interconnected tables with several unique challenges:

Core Performance Tables Overview

Table Key Columns Purpose
HRA_APPRAISALS APPRAISAL_ID, PERSON_ID, APPRAISAL_PERIOD_ID, APPRSL_TYPE, OVERALL_RATING, STATUS_CODE Master appraisal records with ratings and status
HRA_APPRAISAL_PERIODS APPRAISAL_PERIOD_ID, PERIOD_NAME, START_DATE, END_DATE Review cycle definitions (annual, semi-annual, etc.)
HRA_GOALS GOAL_ID, PERSON_ID, GOAL_NAME, TARGET_VALUE, ACTUAL_VALUE, STATUS_CODE, GOAL_TYPE_CODE Individual goals and objectives for employees
HRA_GOAL_PLANS GOAL_PLAN_ID, GOAL_PLAN_NAME, START_DATE, END_DATE Organization goal plan templates and frameworks
HRA_RATING_MODELS RATING_MODEL_ID, RATING_MODEL_NAME, RATING_LEVEL_CODE, NUMERIC_RATING Rating scale definitions (1-5, Exceeds/Meets/Below, etc.)
HRA_PERF_RATINGS PERF_RATING_ID, APPRAISAL_ID, SECTION_ID, RATING_LEVEL_CODE, RATING_MODEL_ID Section and overall ratings for appraisals
HRA_PERF_DOC_TYPES PERF_DOC_TYPE_ID, DOC_TYPE_NAME, TEMPLATE_NAME Performance document templates (standard, tailored)
HRA_PARTICIPANTS PARTICIPANT_ID, APPRAISAL_ID, PERSON_ID, ROLE_CODE Multi-rater feedback participants (manager, peer, direct report)

HRA_APPRAISALS: Appraisals Deep Dive

The HRA_APPRAISALS table is the master record for all performance appraisals. Each row represents one employee's appraisal in a given period.

Column Type Purpose
APPRAISAL_ID NUMBER (PK) Unique appraisal identifier
PERSON_ID NUMBER (FK) Links to PER_ALL_PEOPLE_F, the employee being reviewed
APPRAISAL_PERIOD_ID NUMBER (FK) Links to HRA_APPRAISAL_PERIODS, identifies the review cycle
APPRSL_TYPE VARCHAR2 Type of appraisal (STANDARD, PROBATION, MANAGER, etc.)
OVERALL_RATING VARCHAR2 Overall performance rating code (from rating model)
STATUS_CODE VARCHAR2 Appraisal status: DRAFT, IN_PROGRESS, SUBMITTED, APPROVED, CLOSED
MANAGER_ID NUMBER (FK) Manager conducting the appraisal (PER_ALL_PEOPLE_F)
SUBMITTED_DATE DATE When appraisal was submitted by employee
APPROVED_DATE DATE When appraisal was approved by manager
COMMENTS CLOB Overall appraisal comments and feedback

Key Gotcha: STATUS_CODE is NOT a date-effective field. There is only one active appraisal per employee per period. Always filter by APPRAISAL_PERIOD_ID and STATUS_CODE together.

HRA_APPRAISAL_PERIODS: Review Cycles

This table defines the performance review cycles your organization runs. Each period represents a distinct review window (annual, semi-annual, quarterly).

Column Type Purpose
APPRAISAL_PERIOD_ID NUMBER (PK) Unique period identifier
PERIOD_NAME VARCHAR2 User-friendly name (e.g., "2026 Annual Review")
START_DATE DATE When the review period begins
END_DATE DATE When the review period closes
PERIOD_TYPE VARCHAR2 ANNUAL, SEMI_ANNUAL, QUARTERLY, AD_HOC
SUBMISSION_DUE_DATE DATE Final date for employees to submit self-review
APPROVAL_DUE_DATE DATE Final date for managers to approve reviews
STATUS VARCHAR2 OPEN, IN_PROGRESS, CLOSED

HRA_GOALS: Goals & Objectives

The HRA_GOALS table tracks individual employee goals throughout the performance cycle. Goals are separate from appraisals but are referenced during reviews.

Column Type Purpose
GOAL_ID NUMBER (PK) Unique goal identifier
PERSON_ID NUMBER (FK) Employee who owns the goal
GOAL_PLAN_ID NUMBER (FK) Links to HRA_GOAL_PLANS, the goal framework
GOAL_NAME VARCHAR2 Goal title or description
GOAL_TYPE_CODE VARCHAR2 STRATEGIC, COMPETENCY, DEVELOPMENT, COMPLIANCE
START_DATE DATE When goal tracking begins
END_DATE DATE When goal tracking ends
TARGET_VALUE NUMBER Quantitative target (if applicable)
ACTUAL_VALUE NUMBER Actual achievement against target
STATUS_CODE VARCHAR2 NOT_STARTED, IN_PROGRESS, ACHIEVED, NOT_ACHIEVED
WEIGHT_PERCENTAGE NUMBER Importance relative to overall performance (0-100)

HRA_RATING_MODELS: Rating Scales & Calculations

Rating models define the scales used in appraisals. Organizations can have multiple rating models (1-5 scale, Exceeds/Meets/Below, etc.) depending on role or organizational unit.

Column Type Purpose
RATING_MODEL_ID NUMBER (PK) Unique rating model identifier
RATING_MODEL_NAME VARCHAR2 Model name (e.g., "Standard 5-Point")
RATING_LEVEL_CODE VARCHAR2 Individual rating code (1, 2, 3, 4, 5 or text codes)
NUMERIC_RATING NUMBER Numeric equivalent for calculations
RATING_LEVEL_DESCRIPTION VARCHAR2 Human-readable description (e.g., "Exceeds Expectations")
EFFECTIVE_START_DATE DATE When this rating level is effective
EFFECTIVE_END_DATE DATE When this rating level expires

HRA_PERF_RATINGS: Performance Ratings Storage

This table stores the actual ratings assigned during appraisals. A single appraisal can have multiple ratings (one per section, plus an overall rating).

Column Type Purpose
PERF_RATING_ID NUMBER (PK) Unique rating record identifier
APPRAISAL_ID NUMBER (FK) Links to HRA_APPRAISALS
SECTION_ID NUMBER (FK) Links to appraisal section (optional; NULL = overall rating)
RATING_LEVEL_CODE VARCHAR2 The rating code assigned (1, 2, 3, etc.)
RATING_MODEL_ID NUMBER (FK) Links to HRA_RATING_MODELS for validation and description
RATING_DATE DATE When this rating was assigned
COMMENTS CLOB Section-specific feedback

Performance Review Data Flow

The performance management workflow follows this sequence:

  1. Define Period: Create a new HRA_APPRAISAL_PERIODS (e.g., "2026 Annual Review")
  2. Set Doc Type: Assign a performance document template (HRA_PERF_DOC_TYPES)
  3. Create Appraisals: Generate HRA_APPRAISALS records for each employee in scope
  4. Add Goals: Employees set HRA_GOALS for the period
  5. Manager Reviews: Manager completes appraisal, adding HRA_PERF_RATINGS for each section
  6. 360 Feedback: (Optional) Peers and direct reports provide ratings via HRA_PARTICIPANTS
  7. Overall Rating: Final HRA_PERF_RATINGS record with overall rating stored
  8. Approval: Status moves from DRAFT → IN_PROGRESS → SUBMITTED → APPROVED → CLOSED

8 Production SQL Queries

Query 1: Active Appraisals by Status

Count appraisals by status for the current review period.

-- Active appraisals by status for current period
WITH current_period AS (
    SELECT APPRAISAL_PERIOD_ID, PERIOD_NAME
    FROM HRA_APPRAISAL_PERIODS
    WHERE STATUS = 'OPEN'
      AND TRUNC(SYSDATE) BETWEEN START_DATE AND END_DATE
)
SELECT
    ap.PERIOD_NAME,
    ha.STATUS_CODE,
    COUNT(*) as APPRAISAL_COUNT,
    COUNT(DISTINCT ha.MANAGER_ID) as MANAGER_COUNT,
    ROUND(100.0 * COUNT(*) /
          SUM(COUNT(*)) OVER (PARTITION BY ap.PERIOD_NAME), 1) as PERCENTAGE
FROM HRA_APPRAISALS ha
JOIN current_period ap ON ha.APPRAISAL_PERIOD_ID = ap.APPRAISAL_PERIOD_ID
GROUP BY ap.PERIOD_NAME, ha.STATUS_CODE
ORDER BY ap.PERIOD_NAME,
         CASE ha.STATUS_CODE
           WHEN 'DRAFT' THEN 1
           WHEN 'IN_PROGRESS' THEN 2
           WHEN 'SUBMITTED' THEN 3
           WHEN 'APPROVED' THEN 4
           WHEN 'CLOSED' THEN 5
         END;

Query 2: Overall Performance Ratings Distribution

See the distribution of overall performance ratings across the organization.

-- Performance rating distribution by department
SELECT
    org.NAME as DEPARTMENT,
    rm.RATING_LEVEL_DESCRIPTION,
    COUNT(*) as EMPLOYEE_COUNT,
    ROUND(100.0 * COUNT(*) /
          SUM(COUNT(*)) OVER (PARTITION BY org.NAME), 1) as DISTRIBUTION_PCT
FROM HRA_APPRAISALS ha
JOIN HRA_PERF_RATINGS hpr
  ON ha.APPRAISAL_ID = hpr.APPRAISAL_ID
  AND hpr.SECTION_ID IS NULL  -- Overall rating only
JOIN HRA_RATING_MODELS rm
  ON hpr.RATING_MODEL_ID = rm.RATING_MODEL_ID
  AND TRUNC(SYSDATE) BETWEEN rm.EFFECTIVE_START_DATE
                         AND rm.EFFECTIVE_END_DATE
JOIN PER_ALL_PEOPLE_F p
  ON ha.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
JOIN PER_ALL_ASSIGNMENTS_F a
  ON p.PERSON_ID = a.PERSON_ID
  AND TRUNC(SYSDATE) 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
WHERE ha.STATUS_CODE = 'APPROVED'
  AND ha.APPRAISAL_PERIOD_ID IN (
      SELECT APPRAISAL_PERIOD_ID FROM HRA_APPRAISAL_PERIODS
      WHERE EXTRACT(YEAR FROM END_DATE) = EXTRACT(YEAR FROM SYSDATE)
  )
GROUP BY org.NAME, rm.RATING_LEVEL_DESCRIPTION
ORDER BY org.NAME, rm.NUMERIC_RATING;

Query 3: Goals Completion Rate by Department

Track goal achievement rates across departments.

-- Goal completion rate analysis
WITH goal_summary AS (
    SELECT
        hg.PERSON_ID,
        COUNT(*) as TOTAL_GOALS,
        SUM(CASE WHEN hg.STATUS_CODE = 'ACHIEVED' THEN 1 ELSE 0 END) as ACHIEVED_GOALS,
        ROUND(100.0 * SUM(CASE WHEN hg.STATUS_CODE = 'ACHIEVED' THEN 1 ELSE 0 END) /
              COUNT(*), 1) as ACHIEVEMENT_PCT
    FROM HRA_GOALS hg
    WHERE hg.START_DATE >= TRUNC(SYSDATE, 'YYYY')  -- Current year
    GROUP BY hg.PERSON_ID
)
SELECT
    org.NAME as DEPARTMENT,
    COUNT(*) as EMPLOYEE_COUNT,
    ROUND(AVG(gs.TOTAL_GOALS), 1) as AVG_GOALS_PER_EMPLOYEE,
    ROUND(AVG(gs.ACHIEVED_GOALS), 1) as AVG_ACHIEVED_GOALS,
    ROUND(AVG(gs.ACHIEVEMENT_PCT), 1) as AVG_ACHIEVEMENT_PCT,
    ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY gs.ACHIEVEMENT_PCT), 1) as MEDIAN_ACHIEVEMENT_PCT
FROM goal_summary gs
JOIN PER_ALL_PEOPLE_F p
  ON gs.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
JOIN PER_ALL_ASSIGNMENTS_F a
  ON p.PERSON_ID = a.PERSON_ID
  AND TRUNC(SYSDATE) 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
GROUP BY org.NAME
ORDER BY org.NAME;

Query 4: Overdue Performance Reviews

Find reviews that are past the approval due date but not yet closed.

-- Overdue appraisals not yet approved
SELECT
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PERIOD_NAME,
    ap.APPROVAL_DUE_DATE,
    TRUNC(SYSDATE - ap.APPROVAL_DUE_DATE) as DAYS_OVERDUE,
    ha.STATUS_CODE,
    ha.SUBMITTED_DATE,
    m.DISPLAY_NAME as MANAGER_NAME
FROM HRA_APPRAISALS ha
JOIN HRA_APPRAISAL_PERIODS ap
  ON ha.APPRAISAL_PERIOD_ID = ap.APPRAISAL_PERIOD_ID
JOIN PER_ALL_PEOPLE_F p
  ON ha.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
LEFT JOIN PER_ALL_PEOPLE_F m
  ON ha.MANAGER_ID = m.PERSON_ID
WHERE ap.APPROVAL_DUE_DATE < TRUNC(SYSDATE)
  AND ha.STATUS_CODE NOT IN ('APPROVED', 'CLOSED')
  AND ap.STATUS = 'OPEN'
ORDER BY DAYS_OVERDUE DESC;

Query 5: Manager vs Self-Rating Comparison

Compare manager ratings against employee self-ratings to identify rating gaps.

-- Manager vs self-rating gap analysis
WITH rating_comparison AS (
    SELECT
        ha.APPRAISAL_ID,
        ha.PERSON_ID,
        hpr.RATING_LEVEL_CODE,
        LEAD(hpr.RATING_LEVEL_CODE) OVER (
            PARTITION BY ha.APPRAISAL_ID ORDER BY hpr.RATING_DATE
        ) as SELF_RATING,
        rm.NUMERIC_RATING,
        LEAD(rm.NUMERIC_RATING) OVER (
            PARTITION BY ha.APPRAISAL_ID ORDER BY hpr.RATING_DATE
        ) as SELF_NUMERIC_RATING
    FROM HRA_APPRAISALS ha
    JOIN HRA_PERF_RATINGS hpr
      ON ha.APPRAISAL_ID = hpr.APPRAISAL_ID
      AND hpr.SECTION_ID IS NULL  -- Overall rating only
    JOIN HRA_RATING_MODELS rm
      ON hpr.RATING_MODEL_ID = rm.RATING_MODEL_ID
      AND TRUNC(hpr.RATING_DATE) BETWEEN rm.EFFECTIVE_START_DATE
                                    AND rm.EFFECTIVE_END_DATE
    WHERE ha.STATUS_CODE = 'APPROVED'
)
SELECT
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    rc.RATING_LEVEL_CODE as MANAGER_RATING,
    rc.SELF_RATING,
    rc.NUMERIC_RATING as MANAGER_NUMERIC,
    rc.SELF_NUMERIC_RATING,
    (rc.SELF_NUMERIC_RATING - rc.NUMERIC_RATING) as RATING_GAP,
    CASE
        WHEN rc.SELF_NUMERIC_RATING > rc.NUMERIC_RATING THEN 'Self-Inflated'
        WHEN rc.SELF_NUMERIC_RATING < rc.NUMERIC_RATING THEN 'Self-Modest'
        ELSE 'Aligned'
    END as ALIGNMENT_TYPE
FROM rating_comparison rc
JOIN PER_ALL_PEOPLE_F p
  ON rc.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
WHERE rc.SELF_RATING IS NOT NULL
ORDER BY ABS(RATING_GAP) DESC;

Query 6: 360 Feedback Participant Completion

Track completion rates for 360-degree feedback process.

-- 360 feedback participation and completion tracking
WITH feedback_status AS (
    SELECT
        ha.APPRAISAL_ID,
        ha.PERSON_ID,
        COUNT(*) as TOTAL_PARTICIPANTS,
        SUM(CASE WHEN hp.SUBMISSION_DATE IS NOT NULL THEN 1 ELSE 0 END) as COMPLETED_FEEDBACK,
        ROUND(100.0 * SUM(CASE WHEN hp.SUBMISSION_DATE IS NOT NULL THEN 1 ELSE 0 END) /
              COUNT(*), 1) as COMPLETION_PCT
    FROM HRA_APPRAISALS ha
    LEFT JOIN HRA_PARTICIPANTS hp
      ON ha.APPRAISAL_ID = hp.APPRAISAL_ID
    WHERE ha.STATUS_CODE IN ('IN_PROGRESS', 'SUBMITTED', 'APPROVED')
    GROUP BY ha.APPRAISAL_ID, ha.PERSON_ID
)
SELECT
    p.PERSON_NUMBER,
    p.DISPLAY_NAME,
    ap.PERIOD_NAME,
    fs.TOTAL_PARTICIPANTS,
    fs.COMPLETED_FEEDBACK,
    fs.COMPLETION_PCT,
    CASE
        WHEN fs.COMPLETION_PCT >= 100 THEN 'Complete'
        WHEN fs.COMPLETION_PCT >= 75 THEN 'On Track'
        WHEN fs.COMPLETION_PCT >= 50 THEN 'In Progress'
        ELSE 'Just Started'
    END as STATUS
FROM feedback_status fs
JOIN HRA_APPRAISALS ha
  ON fs.APPRAISAL_ID = ha.APPRAISAL_ID
JOIN HRA_APPRAISAL_PERIODS ap
  ON ha.APPRAISAL_PERIOD_ID = ap.APPRAISAL_PERIOD_ID
JOIN PER_ALL_PEOPLE_F p
  ON fs.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
WHERE fs.TOTAL_PARTICIPANTS > 0
ORDER BY p.DISPLAY_NAME;

Query 7: Performance Trend (Year-over-Year Ratings)

Track how employee performance ratings change year-over-year.

-- Year-over-year performance rating trends
WITH annual_ratings AS (
    SELECT
        p.PERSON_ID,
        p.DISPLAY_NAME,
        EXTRACT(YEAR FROM ap.END_DATE) as REVIEW_YEAR,
        rm.RATING_LEVEL_DESCRIPTION,
        rm.NUMERIC_RATING,
        ROW_NUMBER() OVER (
            PARTITION BY p.PERSON_ID, EXTRACT(YEAR FROM ap.END_DATE)
            ORDER BY ha.APPROVED_DATE DESC
        ) as RN
    FROM HRA_APPRAISALS ha
    JOIN HRA_PERF_RATINGS hpr
      ON ha.APPRAISAL_ID = hpr.APPRAISAL_ID
      AND hpr.SECTION_ID IS NULL  -- Overall rating
    JOIN HRA_RATING_MODELS rm
      ON hpr.RATING_MODEL_ID = rm.RATING_MODEL_ID
    JOIN HRA_APPRAISAL_PERIODS ap
      ON ha.APPRAISAL_PERIOD_ID = ap.APPRAISAL_PERIOD_ID
    JOIN PER_ALL_PEOPLE_F p
      ON ha.PERSON_ID = p.PERSON_ID
    WHERE ha.STATUS_CODE = 'APPROVED'
      AND ap.PERIOD_TYPE = 'ANNUAL'
      AND EXTRACT(YEAR FROM ap.END_DATE) IN (EXTRACT(YEAR FROM SYSDATE) - 1,
                                             EXTRACT(YEAR FROM SYSDATE))
)
SELECT
    ar.PERSON_ID,
    ar.DISPLAY_NAME,
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE) - 1
             THEN ar.NUMERIC_RATING END) as PRIOR_YEAR_RATING,
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE) - 1
             THEN ar.RATING_LEVEL_DESCRIPTION END) as PRIOR_YEAR_DESCRIPTION,
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE)
             THEN ar.NUMERIC_RATING END) as CURRENT_YEAR_RATING,
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE)
             THEN ar.RATING_LEVEL_DESCRIPTION END) as CURRENT_YEAR_DESCRIPTION,
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE)
             THEN ar.NUMERIC_RATING END) -
    MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE) - 1
             THEN ar.NUMERIC_RATING END) as RATING_CHANGE
FROM annual_ratings ar
WHERE ar.RN = 1
GROUP BY ar.PERSON_ID, ar.DISPLAY_NAME
HAVING MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE) - 1
              THEN ar.NUMERIC_RATING END) IS NOT NULL
   AND MAX(CASE WHEN ar.REVIEW_YEAR = EXTRACT(YEAR FROM SYSDATE)
              THEN ar.NUMERIC_RATING END) IS NOT NULL
ORDER BY ABS(RATING_CHANGE) DESC;

Query 8: Headcount by Rating Level for Calibration

Aggregate performance data for calibration meetings and workforce planning.

-- Headcount by rating level for workforce calibration
SELECT
    org.NAME as DEPARTMENT,
    j.NAME as JOB_TITLE,
    rm.RATING_LEVEL_DESCRIPTION,
    COUNT(DISTINCT p.PERSON_ID) as HEADCOUNT,
    ROUND(100.0 * COUNT(DISTINCT p.PERSON_ID) /
          SUM(COUNT(DISTINCT p.PERSON_ID)) OVER (PARTITION BY org.NAME), 1) as DEPT_PERCENTAGE,
    ROUND(100.0 * COUNT(DISTINCT p.PERSON_ID) /
          SUM(COUNT(DISTINCT p.PERSON_ID)) OVER (PARTITION BY org.NAME, j.NAME), 1) as JOB_PERCENTAGE,
    ROUND(AVG(SALARY_COMPONENTS.SALARY_AMOUNT), 0) as AVG_SALARY,
    COUNT(DISTINCT CASE WHEN FLOOR(MONTHS_BETWEEN(TRUNC(SYSDATE), wr.START_DATE) / 12) < 1
                        THEN p.PERSON_ID END) as NEW_HIRES_UNDER_1YR
FROM HRA_APPRAISALS ha
JOIN HRA_PERF_RATINGS hpr
  ON ha.APPRAISAL_ID = hpr.APPRAISAL_ID
  AND hpr.SECTION_ID IS NULL
JOIN HRA_RATING_MODELS rm
  ON hpr.RATING_MODEL_ID = rm.RATING_MODEL_ID
JOIN PER_ALL_PEOPLE_F p
  ON ha.PERSON_ID = p.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                         AND p.EFFECTIVE_END_DATE
JOIN PER_ALL_ASSIGNMENTS_F a
  ON p.PERSON_ID = a.PERSON_ID
  AND TRUNC(SYSDATE) BETWEEN a.EFFECTIVE_START_DATE
                         AND a.EFFECTIVE_END_DATE
  AND a.PRIMARY_FLAG = 'Y'
LEFT JOIN PER_JOBS j
  ON a.JOB_ID = j.JOB_ID
LEFT JOIN HR_ALL_ORGANIZATION_UNITS org
  ON a.ORGANIZATION_ID = org.ORGANIZATION_ID
LEFT JOIN PER_WORK_RELATIONSHIPS wr
  ON p.PERSON_ID = wr.PERSON_ID
  AND wr.PRIMARY_FLAG = 'Y'
LEFT JOIN (
    SELECT PERSON_ID, SUM(SALARY_AMOUNT) as SALARY_AMOUNT
    FROM CMP_SALARY
    WHERE TRUNC(SYSDATE) BETWEEN EFFECTIVE_START_DATE AND EFFECTIVE_END_DATE
    GROUP BY PERSON_ID
) SALARY_COMPONENTS
  ON p.PERSON_ID = SALARY_COMPONENTS.PERSON_ID
WHERE ha.STATUS_CODE = 'APPROVED'
  AND EXTRACT(YEAR FROM (SELECT MAX(END_DATE)
                          FROM HRA_APPRAISAL_PERIODS
                          WHERE APPRAISAL_PERIOD_ID = ha.APPRAISAL_PERIOD_ID))
      = EXTRACT(YEAR FROM SYSDATE)
GROUP BY org.NAME, j.NAME, rm.RATING_LEVEL_DESCRIPTION, rm.NUMERIC_RATING
ORDER BY org.NAME, j.NAME, rm.NUMERIC_RATING DESC;

Join Patterns & Best Practices

Date-Effective Filtering

Always use this pattern for date-effective tables like rating models:

AND TRUNC(SYSDATE) BETWEEN table_alias.EFFECTIVE_START_DATE
                         AND table_alias.EFFECTIVE_END_DATE

Core Entity Chain

To get from appraisal to department, use this proven chain:

HRA_APPRAISALS → PER_ALL_PEOPLE_F → PER_ALL_ASSIGNMENTS_F → HR_ALL_ORGANIZATION_UNITS

Rating Model Lookup

Always join HRA_PERF_RATINGS to HRA_RATING_MODELS with date-effective filtering:

JOIN HRA_RATING_MODELS rm
  ON hpr.RATING_MODEL_ID = rm.RATING_MODEL_ID
  AND TRUNC(hpr.RATING_DATE) BETWEEN rm.EFFECTIVE_START_DATE
                                AND rm.EFFECTIVE_END_DATE

Overall vs Section Ratings

Key Gotcha: In HRA_PERF_RATINGS, when SECTION_ID is NULL, it's the overall appraisal rating. Always include this filter for aggregate reporting:

WHERE hpr.SECTION_ID IS NULL  -- Only overall ratings

Frequently Asked Questions

What is HRA_APPRAISALS in Oracle HCM?

HRA_APPRAISALS is the master table for performance appraisals. It stores individual appraisal records with data such as the employee ID, appraisal period, appraisal type, overall rating, and status. Each appraisal can have multiple sections, goals, and ratings stored in related tables like HRA_PERF_RATINGS.

How do I query performance ratings in Oracle Fusion?

Use HRA_PERF_RATINGS joined with HRA_APPRAISALS and PER_ALL_PEOPLE_F, ensuring proper date-effective filtering. Always join HRA_RATING_MODELS to get the human-readable rating names. Filter for SECTION_ID IS NULL to get overall ratings, and use proper date-effective syntax: TRUNC(SYSDATE) BETWEEN EFFECTIVE_START_DATE AND EFFECTIVE_END_DATE.

What OTBI subject area covers performance management?

The OTBI subject area for performance management is "Workforce Performance - Performance Document Real Time". It provides real-time access to appraisal data, performance ratings, goals, and review cycle information directly from the HRA_ tables without the latency of the data warehouse.

How do goals relate to appraisals in Oracle HCM?

Goals (HRA_GOALS) are tracked separately from appraisals but within the same performance cycle. An employee sets goals at the beginning of an appraisal period. These goals are then referenced in the appraisal document and may influence the performance rating. Goals have their own status and achievement tracking independent of the appraisal.

What is a performance document type in Oracle HCM?

A performance document type (HRA_PERF_DOC_TYPES) defines the template and structure for appraisal documents. It specifies which sections appear in the appraisal, which rating models apply to each section, required fields, and workflow rules for the performance review process in a specific organization or for a specific review cycle.

Need Performance Management Configuration Help?

Get expert guidance on Oracle HCM performance management implementation, reporting, and data integration.

Find Consultants

Understanding Oracle HCM's performance management tables enables sophisticated talent reviews, goal tracking, and performance analytics. The modular design separates appraisals, ratings, goals, and feedback, giving your organization flexibility in how you structure performance processes.

Combine performance data with core HCM entities for comprehensive talent analytics, and leverage the OTBI "Workforce Performance" subject area for real-time reporting without writing SQL. Whether you're building calibration dashboards, tracking goal completion, or analyzing performance trends, these queries provide a solid foundation for your reporting layer.