Advanced Oracle SQL Query Examples

By Ercan - 15/06/2025 - 0 comments

When working with Oracle databases, you often go beyond simple SELECT statements. Real-world data is hierarchical, analytical, and sometimes messy. In this article, we’ll explore powerful Oracle SQL techniques that solve complex data problems — using realistic examples and sample tables.

We’ll cover partitions, hierarchies, analytics, and more. Each example includes setup scripts and queries you can run directly in your Oracle environment.


Sample Schema Setup

Let’s start by creating two simple but related tables: departments and employees.

CREATE TABLE departments (
  dept_id NUMBER PRIMARY KEY,
  dept_name VARCHAR2(50)
);

CREATE TABLE employees (
  emp_id NUMBER PRIMARY KEY,
  emp_name VARCHAR2(50),
  manager_id NUMBER,
  dept_id NUMBER,
  salary NUMBER,
  hire_date DATE,
  FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);

Now insert a few rows:

INSERT INTO departments VALUES (1, 'Engineering');
INSERT INTO departments VALUES (2, 'Sales');

INSERT INTO employees VALUES (101, 'Alice', NULL, 1, 9500, DATE '2020-01-15');
INSERT INTO employees VALUES (102, 'Bob', 101, 1, 7200, DATE '2021-03-10');
INSERT INTO employees VALUES (103, 'Carol', 101, 2, 6800, DATE '2022-07-25');
INSERT INTO employees VALUES (104, 'David', 102, 1, 6000, DATE '2023-05-05');
INSERT INTO employees VALUES (105, 'Eve', 103, 2, 6400, DATE '2024-02-11');

1. Partition Queries: Ranking Employees Within Departments

Partitioning functions let you perform grouped operations without collapsing rows.
Let’s find the top two earners in each department.

SELECT dept_id, emp_name, salary
FROM (
  SELECT dept_id, emp_name, salary,
         ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rn
  FROM employees
)
WHERE rn <= 2;

Explanation:

  • PARTITION BY dept_id restarts ranking for each department.
  • ORDER BY salary DESC sorts employees within that partition.
  • The outer query filters only the top two.

2. Hierarchical Queries: Manager → Employee Tree

Oracle’s CONNECT BY PRIOR syntax makes it easy to traverse hierarchical relationships such as organizational charts.

SELECT LPAD(' ', LEVEL * 2) || emp_name AS hierarchy
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR emp_id = manager_id;

Explanation:

  • START WITH manager_id IS NULL selects the root (top-level manager).
  • CONNECT BY PRIOR recursively finds subordinates.
  • LEVEL indicates the hierarchy depth and can be used for indentation.

This is one of Oracle’s oldest but still most elegant features.


3. Recursive WITH Queries: A Modern Hierarchy Alternative

In modern Oracle versions, you can achieve the same result with a recursive WITH clause.

WITH emp_hierarchy (emp_id, emp_name, manager_id, level_no) AS (
  SELECT emp_id, emp_name, manager_id, 1 AS level_no
  FROM employees
  WHERE manager_id IS NULL
  UNION ALL
  SELECT e.emp_id, e.emp_name, e.manager_id, h.level_no + 1
  FROM employees e
  JOIN emp_hierarchy h ON e.manager_id = h.emp_id
)
SELECT LPAD(' ', level_no * 2) || emp_name AS hierarchy
FROM emp_hierarchy;

Tip: Recursive CTEs are more flexible for modern applications because you can join, filter, or aggregate inside the recursion.


4. Analytical Functions: Comparing Salaries Over Time

Analytical functions such as LAG() and LEAD() help analyze sequential data — for example, tracking salary changes.

SELECT emp_id, emp_name, salary,
       LAG(salary) OVER (ORDER BY hire_date) AS previous_salary,
       salary - LAG(salary) OVER (ORDER BY hire_date) AS salary_diff
FROM employees;

Explanation:

  • LAG(salary) returns the previous row’s salary.
  • salary_diff shows how much each employee’s salary differs from the last hired employee.

5. PIVOT Queries: Converting Rows to Columns

Oracle’s PIVOT clause lets you dynamically reshape data. Here’s an example that aggregates salaries by department.

SELECT *
FROM (
  SELECT dept_id, emp_name, salary
  FROM employees
)
PIVOT (
  SUM(salary) FOR dept_id IN (1 AS Engineering, 2 AS Sales)
);


Explanation:

  • The inner query provides base data.
  • PIVOT transforms department IDs into columns.
  • Each cell contains the sum of salaries in that department.

This is extremely useful in reporting and data visualization.


6. JSON Queries: Extracting Structured Data

If you store JSON data in Oracle (from version 12c onward), you can query it directly using JSON_TABLE.

CREATE TABLE projects (
  project_id NUMBER PRIMARY KEY,
  project_data CLOB CHECK (project_data IS JSON)
);

INSERT INTO projects VALUES (1, '{"name": "Apollo", "team": ["Alice","Bob"], "budget": 25000}');
INSERT INTO projects VALUES (2, '{"name": "Zeus", "team": ["Carol","Eve"], "budget": 18000}');

SELECT p.project_id, jt.name, jt.budget
FROM projects p,
     JSON_TABLE(p.project_data, '$'
       COLUMNS (
         name VARCHAR2(50) PATH '$.name',
         budget NUMBER PATH '$.budget'
       )
     ) jt;

Result:

PROJECT_ID NAME BUDGET
1 Apollo 25000
2 Zeus 18000


Note: You can also extract nested arrays or objects by using NESTED PATH inside JSON_TABLE.


7. Conditional Aggregation: Dynamic Summaries

You can conditionally aggregate data without writing multiple queries by using CASE WHEN.

SELECT
  SUM(CASE WHEN dept_id = 1 THEN salary ELSE 0 END) AS eng_total,
  SUM(CASE WHEN dept_id = 2 THEN salary ELSE 0 END) AS sales_total
FROM employees;

This is the manual equivalent of PIVOT and works in databases that don’t support it.


8. Performance Tip: Inline Views and Materialization Hints

When your subqueries are reused multiple times, Oracle might re-evaluate them. You can use the MATERIALIZE hint to force caching of results.

SELECT /*+ MATERIALIZE */ *
FROM (
  SELECT dept_id, AVG(salary) AS avg_salary
  FROM employees
  GROUP BY dept_id
) v
WHERE v.avg_salary > 7000;

This can help when dealing with large datasets or analytical dashboards.


Final Notes

Oracle SQL offers an incredibly rich feature set — far beyond what basic tutorials cover. Partitioned queries, hierarchical traversal, analytical functions, and JSON querying can significantly reduce application logic by pushing intelligence to the database layer.

Experimenting with these techniques on small datasets helps you understand how Oracle’s optimizer works and how to design more efficient SQL for real-world enterprise systems.

Tags: oracle