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.
Table of Contents
- Why Performance Management Data Is Hard to Query
- Core Performance Tables Overview
- HRA_APPRAISALS: Appraisals Deep Dive
- HRA_APPRAISAL_PERIODS: Review Cycles
- HRA_GOALS: Goals & Objectives
- HRA_RATING_MODELS: Rating Scales & Calculations
- HRA_PERF_RATINGS: Performance Ratings Storage
- Performance Review Data Flow
- 8 Production SQL Queries
- Join Patterns & Best Practices
- Frequently Asked Questions
Why Performance Management Data Is Hard to Query
Performance management in Oracle HCM spans multiple interconnected tables with several unique challenges:
- Date-effective records: Appraisal periods, rating models, and goals all use effective-dating. You must filter for current records using EFFECTIVE_START_DATE and EFFECTIVE_END_DATE.
- Hierarchical ratings: Performance ratings reference rating models, which have multiple levels. A single appraisal can have ratings at multiple sections, requiring careful joining.
- Multi-rater feedback: 360-degree reviews involve multiple participants (managers, peers, direct reports) creating complex join paths.
- Goal-to-rating linkage: Goals are tracked separately from appraisals but are referenced during review periods, requiring LEFT JOINs to avoid losing appraisals.
- OTBI complexity: The OTBI subject area
Workforce Performance - Performance Document Real Timeexposes these tables with pre-built hierarchies, but direct SQL requires understanding the full data model.
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:
- Define Period: Create a new HRA_APPRAISAL_PERIODS (e.g., "2026 Annual Review")
- Set Doc Type: Assign a performance document template (HRA_PERF_DOC_TYPES)
- Create Appraisals: Generate HRA_APPRAISALS records for each employee in scope
- Add Goals: Employees set HRA_GOALS for the period
- Manager Reviews: Manager completes appraisal, adding HRA_PERF_RATINGS for each section
- 360 Feedback: (Optional) Peers and direct reports provide ratings via HRA_PARTICIPANTS
- Overall Rating: Final HRA_PERF_RATINGS record with overall rating stored
- 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 ConsultantsUnderstanding 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.