Popular Searches
Popular Course Categories
Popular Courses

Finding the Second-Highest and Nth-Highest Values

Finding the Second-Highest and Nth-Highest Values

Advanced SQL Queries and Set Operations

Finding the Second-Highest and Nth-Highest Values in MySQL

Course: MySQL Training

Topic: Finding the Second-Highest and Nth-Highest Values Using SQL Queries

Course Link: MySQL Training Course

Demo Link: Register for a Free Course Demo


1. Introduction

Finding the second-highest and Nth-highest values is a common SQL interview question and an important database querying skill. In MySQL, these problems frequently involve identifying the second-highest salary in an employee table, the third-highest product price, the fifth-highest sales amount, or another ranked value from a dataset.

There are several ways to solve these problems, including using MAX(), subqueries, DISTINCT, ORDER BY, LIMIT, and window functions such as DENSE_RANK() and ROW_NUMBER(). The appropriate method depends on whether duplicate values should count as separate positions and which MySQL version is being used.

For example, consider the following employee salaries:

Employee ID Employee Name Salary
1 Amit 90000
2 Neha 75000
3 Rahul 60000
4 Priya 75000
5 Vikas 50000

The highest salary is 90000. The second-highest distinct salary is 75000, even though two employees receive that salary. The third-highest distinct salary is 60000.

1.1 Learning Objectives

  • Understand highest, second-highest, and Nth-highest values.
  • Identify the difference between distinct ranking and row-based ranking.
  • Use aggregate functions and subqueries to find the second-highest value.
  • Use LIMIT and OFFSET to retrieve ranked values.
  • Apply ROW_NUMBER(), RANK(), and DENSE_RANK().
  • Handle duplicate values, NULL values, and cases where the requested rank does not exist.
  • Choose an appropriate query for interviews and real-world applications.

2. Understanding the Highest and Nth-Highest Values

2.1 Highest Value

The highest value is the maximum value in a column. For a salary column, it represents the largest salary recorded in the table.

SELECT MAX(salary) AS highest_salary
FROM employees;

Explanation:

  • MAX(salary) returns the largest non-NULL salary.
  • AS highest_salary assigns a readable name to the result column.
  • The query returns one value rather than an entire employee record.

2.2 Second-Highest Value

The second-highest value is commonly understood as the second-largest distinct value. If salaries are 90000, 75000, 75000, 60000, and 50000, the second-highest distinct salary is 75000, not another occurrence of 90000 or 75000.

However, some questions ask for the second row after sorting, where duplicate values may occupy separate positions. Always clarify the expected meaning before selecting a query.

2.3 Nth-Highest Value

The Nth-highest value is the value at position N when distinct values are sorted in descending order, unless the problem explicitly specifies row-based ranking.

Rank Distinct Salary
1st highest 90000
2nd highest 75000
3rd highest 60000
4th highest 50000

When distinct values are required, duplicate salaries count only once in the ranking.

3. Creating a Sample Database Table

Before practicing these queries, create a database table containing employee information.

3.1 Create the Database

CREATE DATABASE company_db;
USE company_db;

CREATE DATABASE creates a database, while USE selects it for subsequent operations.

3.2 Create the Employees Table

CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(100),
    department VARCHAR(50),
    salary DECIMAL(10, 2)
);

Column descriptions:

Column Purpose
employee_id Unique identifier for each employee.
employee_name Name of the employee.
department Department to which the employee belongs.
salary Employee salary, stored as a decimal number.

3.3 Insert Sample Records

INSERT INTO employees
(employee_id, employee_name, department, salary)
VALUES
(1, 'Amit', 'IT', 90000),
(2, 'Neha', 'HR', 75000),
(3, 'Rahul', 'IT', 60000),
(4, 'Priya', 'Finance', 75000),
(5, 'Vikas', 'Sales', 50000),
(6, 'Sneha', 'IT', 45000),
(7, 'Karan', 'Finance', 40000);

3.4 Display the Data

SELECT *
FROM employees
ORDER BY salary DESC;

The ORDER BY salary DESC clause sorts the salaries from highest to lowest. The resulting order helps visualize the rankings, but it does not automatically remove duplicate salaries.

4. Method 1: Using MAX() and a Subquery

A subquery is a query placed inside another SQL query. One of the simplest ways to find the second-highest distinct salary is to find the maximum salary that is smaller than the overall maximum.

4.1 Query for the Second-Highest Salary

SELECT MAX(salary) AS second_highest_salary
FROM employees
WHERE salary < (
    SELECT MAX(salary)
    FROM employees
);

4.2 How the Query Works

  1. The inner query, SELECT MAX(salary) FROM employees, finds the highest salary.
  2. The outer query filters out salaries equal to or greater than the highest salary.
  3. The remaining rows contain salaries below the maximum.
  4. The outer MAX(salary) returns the largest value among those remaining salaries.

For the sample data, the highest salary is 90000. The largest salary below 90000 is 75000, so the query returns 75000.

4.3 Advantages

  • Easy to understand and remember.
  • Works in older MySQL versions.
  • Returns the second-highest distinct value even when the highest salary appears multiple times.
  • Does not require sorting the entire result set explicitly.

4.4 Limitation

This query is specifically designed for the second-highest value. It does not directly generalize to every Nth-highest value without adding more nested queries or changing the approach.

5. Method 2: Using DISTINCT, ORDER BY, LIMIT, and OFFSET

MySQL supports LIMIT and OFFSET for selecting a limited number of rows from a result set. Combined with DISTINCT and descending sorting, they provide a convenient way to find ranked distinct values.

5.1 Find the Second-Highest Distinct Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

5.2 Explanation

  • DISTINCT salary removes duplicate salary values.
  • WHERE salary IS NOT NULL excludes missing salaries.
  • ORDER BY salary DESC sorts salaries from highest to lowest.
  • OFFSET 1 skips the first distinct salary.
  • LIMIT 1 returns the next salary only.

The result is 75000 for the sample data.

5.3 Understanding LIMIT and OFFSET

Clause Meaning Example
LIMIT 1 OFFSET 0 Return the first row. Highest value
LIMIT 1 OFFSET 1 Skip one row and return the next. Second-highest value
LIMIT 1 OFFSET 2 Skip two rows and return the next. Third-highest value
LIMIT 1 OFFSET 3 Skip three rows and return the next. Fourth-highest value

5.4 Alternative LIMIT Syntax

MySQL also supports the comma-separated form of LIMIT:

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1, 1;

In this form, the first number is the offset and the second number is the row count. Although valid, LIMIT 1 OFFSET 1 is often easier to read.

5.5 Advantages and Limitations

Advantages:

  • Short and readable syntax.
  • Works in MySQL versions that support basic LIMIT.
  • Can be adapted to any fixed rank by changing the offset.

Limitations:

  • Large offsets may require the database to process many preceding rows.
  • The query returns a salary value, not necessarily the employee details associated with it.
  • Without DISTINCT, duplicate values can occupy multiple positions.

6. Method 3: Finding the Nth-Highest Value with LIMIT and OFFSET

To find the Nth-highest distinct salary, skip the first N-1 distinct salaries and return one row.

6.1 General Query

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET N_MINUS_1;

N_MINUS_1 is a placeholder, not a literal MySQL keyword. Replace it with the required numeric offset.

6.2 Find the Third-Highest Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 2;

Result: 60000.

6.3 Find the Fourth-Highest Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 3;

Result: 50000.

6.4 Find the Fifth-Highest Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 4;

Result: 45000.

6.5 Nth-Highest Value Formula

For a positive integer N:

  • Sort distinct values in descending order.
  • Calculate the offset as N - 1.
  • Return one row.

The general relationship is:

OFFSET = N - 1
LIMIT = 1

If N is 1, the offset is 0. If N is 2, the offset is 1. If N is 5, the offset is 4.

7. Method 4: Using DENSE_RANK()

DENSE_RANK() is a window function that assigns a rank to each row based on the ordering of values. Rows with equal values receive the same rank, and the next distinct value receives the next consecutive rank.

Window functions such as DENSE_RANK() are available in MySQL 8.0 and later.

7.1 Query to Find the Second-Highest Salary

WITH ranked_salaries AS (
    SELECT
        employee_id,
        employee_name,
        salary,
        DENSE_RANK() OVER (
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, salary
FROM ranked_salaries
WHERE salary_rank = 2;

7.2 Explanation

  1. The common table expression, or CTE, is named ranked_salaries.
  2. The inner query calculates a rank for each employee according to salary.
  3. DENSE_RANK() assigns the same rank to employees with equal salaries.
  4. The outer query selects employees whose salary rank is 2.

Because Neha and Priya both earn 75000, both employees receive rank 2. The query returns both records.

7.3 Find the Nth-Highest Salary

WITH ranked_salaries AS (
    SELECT
        employee_id,
        employee_name,
        salary,
        DENSE_RANK() OVER (
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, salary
FROM ranked_salaries
WHERE salary_rank = 3;

Changing salary_rank = 3 to another positive integer retrieves employees at that distinct salary rank.

7.4 Why DENSE_RANK() Is Useful

  • It handles duplicate values correctly for distinct ranking.
  • It returns all rows that share the requested rank.
  • It can rank salaries, prices, scores, sales, and other numeric values.
  • It is easier to extend when the requirement changes from the second-highest to the Nth-highest value.

8. Method 5: Using ROW_NUMBER()

ROW_NUMBER() assigns a unique sequential number to every row based on the specified ordering. Unlike DENSE_RANK(), it does not assign the same number to rows with equal salaries.

8.1 Query for the Second Row by Salary

WITH numbered_employees AS (
    SELECT
        employee_id,
        employee_name,
        salary,
        ROW_NUMBER() OVER (
            ORDER BY salary DESC, employee_id ASC
        ) AS row_num
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, salary
FROM numbered_employees
WHERE row_num = 2;

The query sorts by salary in descending order and uses employee ID as a tie-breaker. If two employees have the same salary, their order is determined by employee ID.

8.2 Find the Nth Row

WITH numbered_employees AS (
    SELECT
        employee_id,
        employee_name,
        salary,
        ROW_NUMBER() OVER (
            ORDER BY salary DESC, employee_id ASC
        ) AS row_num
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, salary
FROM numbered_employees
WHERE row_num = 3;

This query returns the third row in the sorted employee list, not necessarily the third-highest distinct salary.

8.3 When to Use ROW_NUMBER()

  • When every row needs a unique sequential position.
  • When the requirement explicitly refers to the Nth row.
  • When you need to select one record from each group using a deterministic ordering.
  • When duplicate values should occupy separate positions.

9. Method 6: Understanding RANK()

RANK() is another window function. Equal values receive the same rank, but the next rank is skipped according to the number of tied rows.

For example, if salaries are 90000, 75000, 75000, and 60000, the rankings are:

Salary ROW_NUMBER() RANK() DENSE_RANK()
90000 1 1 1
75000 2 2 2
75000 3 2 2
60000 4 4 3

9.1 Query Using RANK()

WITH ranked_employees AS (
    SELECT
        employee_id,
        employee_name,
        salary,
        RANK() OVER (
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, salary
FROM ranked_employees
WHERE salary_rank = 2;

This query returns all employees with rank 2. In this example, both employees earning 75000 are included.

9.2 RANK() Versus DENSE_RANK()

Both functions assign the same rank to tied values. The difference appears after a tie:

  • RANK() leaves gaps in the ranking.
  • DENSE_RANK() does not leave gaps.

For the Nth-highest distinct salary, DENSE_RANK() is usually the most direct window-function solution.

10. Comparing the Different Methods

Method Best Use Duplicate Handling MySQL Compatibility
MAX() with subquery Second-highest value Finds the next distinct value when using less-than comparison Works in older versions
DISTINCT with LIMIT Second or Nth distinct value Duplicates removed Works in older versions
DENSE_RANK() Nth-highest distinct rank and all matching records Same value gets same rank; no gaps MySQL 8.0+
RANK() Competition-style ranking Ties share rank; gaps can appear MySQL 8.0+
ROW_NUMBER() Nth row in a sorted result Every row gets a unique number MySQL 8.0+

11. Handling Duplicate Values Correctly

Duplicate values are one of the most important considerations when solving ranking problems. The correct query depends on whether you need distinct values or individual rows.

11.1 Example Dataset

Employee Salary
Amit 100000
Neha 90000
Rahul 90000
Priya 80000

11.2 Second-Highest Distinct Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

Result: 90000.

11.3 Second Row After Sorting

SELECT employee_id, employee_name, salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC, employee_id ASC
LIMIT 1 OFFSET 1;

This returns one employee from the second sorted position. When the highest salary is unique, this will be an employee with the second-highest salary. If the highest salary occurs multiple times, the second row may have the same salary as the highest row.

11.4 Return Every Employee with the Second-Highest Salary

SELECT employee_id, employee_name, salary
FROM employees
WHERE salary = (
    SELECT MAX(salary)
    FROM employees
    WHERE salary < (
        SELECT MAX(salary)
        FROM employees
    )
);

This returns every employee whose salary equals the second-highest distinct salary.

12. Returning Employee Details Along with the Nth-Highest Salary

Sometimes the requirement is not simply to return a salary value. You may need the employee ID, name, department, and salary of every employee who earns the Nth-highest distinct salary.

12.1 Using DENSE_RANK()

WITH ranked_employees AS (
    SELECT
        employee_id,
        employee_name,
        department,
        salary,
        DENSE_RANK() OVER (
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT
    employee_id,
    employee_name,
    department,
    salary
FROM ranked_employees
WHERE salary_rank = 2
ORDER BY employee_id;

This query returns all employee records at the second-highest distinct salary rank.

12.2 Using a Subquery

SELECT employee_id, employee_name, department, salary
FROM employees
WHERE salary = (
    SELECT DISTINCT salary
    FROM employees
    WHERE salary IS NOT NULL
    ORDER BY salary DESC
    LIMIT 1 OFFSET 1
);

The inner query identifies the second-highest distinct salary. The outer query retrieves all employees whose salary matches that value.

13. Using a Parameter for Nth-Highest Salary

In an application or stored procedure, the requested rank may be supplied dynamically. A MySQL session variable can represent the desired rank when used with a query that supports the chosen syntax.

13.1 Example with a Session Variable

SET @n = 3;

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 2;

The example uses a fixed offset of 2 for rank 3. MySQL does not allow a variable to be substituted for every SQL syntax element in all contexts, so applications should validate N and calculate the offset carefully before constructing a query. Where supported by the application driver, use parameterized SQL for data values and validate any rank used in a LIMIT/OFFSET clause.

13.2 Validate the Requested Rank

The requested rank should be a positive integer. A rank of 0 or a negative rank does not represent a valid Nth-highest value.

-- Example validation concept:
-- N must be an integer greater than or equal to 1.
SET @n = 3;

-- Offset is N - 1.
SET @offset_value = @n - 1;

For application code, validate the value before running the query. Do not accept arbitrary SQL fragments from user input.

14. Handling NULL Values

In MySQL, NULL represents a missing or unknown value. Aggregate functions such as MAX() ignore NULL values. However, sorting and ranking queries should make the intended treatment of NULL explicit.

14.1 Exclude NULL Salaries

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

14.2 Why Use IS NOT NULL?

  • It clearly defines that only actual salary values should be ranked.
  • It avoids confusion about how missing values appear in ordered results.
  • It makes the query's business rule explicit.

14.3 What If All Values Are NULL?

If all salaries are NULL, MAX(salary) returns NULL, and there is no valid second-highest salary. A query using DISTINCT and filtering out NULL values returns no rows.

15. Handling Cases Where the Nth-Highest Value Does Not Exist

A table may not contain enough distinct values to satisfy the requested rank. For example, if the distinct salaries are only 90000 and 75000, a third-highest distinct salary does not exist.

15.1 Example

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 4;

If there are fewer than five distinct non-NULL salary values, this query returns an empty result set.

15.2 Return NULL Instead of an Empty Result

If an application requires one result row even when the requested rank does not exist, a scalar subquery can return NULL when there is no matching value.

SELECT (
    SELECT DISTINCT salary
    FROM employees
    WHERE salary IS NOT NULL
    ORDER BY salary DESC
    LIMIT 1 OFFSET 1
) AS second_highest_salary;

If no second-highest distinct salary exists, the scalar subquery produces NULL.

15.3 Why This Matters

  • Applications can distinguish a missing rank from a valid numeric result.
  • Reports can display a meaningful message instead of an unexpected missing row.
  • Automated tests can verify both normal and boundary cases.

16. Finding the Nth-Highest Value Within Each Department

Some problems ask for the second-highest salary in each department instead of across the entire company. This requires partitioning the ranking by department.

16.1 Second-Highest Distinct Salary in Each Department

WITH department_salary_ranks AS (
    SELECT
        employee_id,
        employee_name,
        department,
        salary,
        DENSE_RANK() OVER (
            PARTITION BY department
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT
    employee_id,
    employee_name,
    department,
    salary
FROM department_salary_ranks
WHERE salary_rank = 2
ORDER BY department, employee_id;

16.2 Explanation of PARTITION BY

  • PARTITION BY department divides employees into department groups.
  • ORDER BY salary DESC sorts salaries within each department.
  • DENSE_RANK() starts ranking at 1 for each department.
  • salary_rank = 2 selects employees at the second-highest distinct salary in their own department.

16.3 Example Business Uses

  • Find the second-highest-paid employee salary in every department.
  • Identify the third-most-expensive product in each category.
  • Find the second-highest sales total for each region.
  • Compare top-performing students within each class.

17. Finding the Nth-Highest Product Price

The same techniques work for any numeric column. Consider a product table containing product IDs, product names, and prices.

17.1 Sample Table

CREATE TABLE products (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(100),
    price DECIMAL(10, 2)
);

17.2 Find the Second-Highest Distinct Price

SELECT DISTINCT price
FROM products
WHERE price IS NOT NULL
ORDER BY price DESC
LIMIT 1 OFFSET 1;

17.3 Find the Third-Highest Distinct Price

SELECT DISTINCT price
FROM products
WHERE price IS NOT NULL
ORDER BY price DESC
LIMIT 1 OFFSET 2;

17.4 Retrieve Products at the Second-Highest Price

SELECT product_id, product_name, price
FROM products
WHERE price = (
    SELECT DISTINCT price
    FROM products
    WHERE price IS NOT NULL
    ORDER BY price DESC
    LIMIT 1 OFFSET 1
);

This returns every product whose price equals the second-highest distinct price.

18. Finding the Nth-Highest Sales Amount

Ranking can also be applied to sales transactions or summarized sales totals. The important consideration is whether you are ranking individual transaction amounts or aggregated sales per employee, customer, or region.

18.1 Rank Individual Transaction Amounts

SELECT DISTINCT transaction_amount
FROM sales
WHERE transaction_amount IS NOT NULL
ORDER BY transaction_amount DESC
LIMIT 1 OFFSET 2;

This returns the third-highest distinct transaction amount.

18.2 Rank Total Sales by Employee

WITH employee_sales AS (
    SELECT
        employee_id,
        SUM(sales_amount) AS total_sales
    FROM sales
    GROUP BY employee_id
),
ranked_sales AS (
    SELECT
        employee_id,
        total_sales,
        DENSE_RANK() OVER (
            ORDER BY total_sales DESC
        ) AS sales_rank
    FROM employee_sales
)
SELECT employee_id, total_sales
FROM ranked_sales
WHERE sales_rank = 2;

This query first calculates total sales for each employee and then ranks those totals. It finds employees tied at the second-highest total sales value.

19. Troubleshooting Common Errors

19.1 Duplicate Values Produce an Unexpected Result

Problem: The second row has the same value as the first row.

Cause: The query sorts individual records but does not remove duplicate values.

Solution: Use DISTINCT for distinct-value ranking or DENSE_RANK() for ranked records.

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

19.2 The Query Returns No Rows

Problem: The query does not return a result for the requested rank.

Possible causes:

  • The table contains fewer distinct non-NULL values than the requested rank.
  • All values are NULL or the table is empty.
  • A WHERE condition filters out the relevant records.
  • The offset is incorrect.

Solution: Check the distinct values and confirm that N is valid.

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC;

19.3 The Query Returns Only a Salary, Not an Employee

Problem: The result includes a numeric value but no employee details.

Cause: The query selects only the salary column or uses an aggregate function such as MAX().

Solution: Use a subquery to retrieve matching employee records or use DENSE_RANK() in a CTE.

19.4 Window Function Syntax Error

Problem: MySQL reports an error when using DENSE_RANK() or ROW_NUMBER().

Cause: The server may be running a MySQL version earlier than 8.0.

Solution: Check the server version and use a compatible alternative such as MAX() with a subquery or DISTINCT with LIMIT.

SELECT VERSION();

19.5 An Incorrect Nth-Highest Value Is Returned

Problem: The returned value does not match the expected rank.

Cause: The offset may not equal N-1, or duplicate values may be included unintentionally.

Solution: Verify the ranking requirement, use DISTINCT when needed, and calculate the offset correctly.

19.6 Non-Deterministic Row Ordering

Problem: Employees with equal salaries appear in a different order across executions.

Cause: The query sorts only by salary, leaving tied rows without a specified order.

Solution: Add a unique tie-breaker such as employee ID when using row-based ranking.

SELECT employee_id, employee_name, salary
FROM employees
ORDER BY salary DESC, employee_id ASC;

20. Performance and Best Practices

20.1 Use an Appropriate Index

If the table contains many records and salary ranking is a frequent operation, an index on the salary column may help the database access or order values more efficiently. Actual performance depends on the query plan, table size, data distribution, and other indexes.

CREATE INDEX idx_employees_salary
ON employees(salary);

Indexes require storage and add overhead to inserts, updates, and deletes. Create them based on measured workload rather than automatically adding an index for every column.

20.2 Use DISTINCT When Ranking Unique Values

Use DISTINCT with LIMIT when the goal is a single Nth-highest distinct value. Use DENSE_RANK() when the goal is to retrieve every record belonging to a distinct rank.

20.3 Avoid Unnecessary Nested Queries

For a fixed second-highest value, a simple MAX() subquery is often sufficient. For a dynamic Nth-highest value, a DISTINCT and LIMIT query or a window function may be more readable.

20.4 Handle NULL Values Intentionally

Decide whether NULL values should be excluded or handled separately. For salary ranking, excluding NULL salaries is usually the clearest choice.

20.5 Clarify the Ranking Requirement

Before writing the query, decide whether you need:

  • The Nth-highest distinct value.
  • The Nth row after sorting.
  • Every record with the Nth-highest distinct value.
  • The Nth-highest value within each group.

20.6 Use EXPLAIN to Inspect Query Plans

For performance analysis, use EXPLAIN to inspect how MySQL plans to execute a query.

EXPLAIN
SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

Review the plan and test with realistic data before deciding whether an index or query rewrite is necessary.

21. Practical Project: Employee Salary Ranking

Project Objective: Create a set of SQL queries that identifies the highest, second-highest, and Nth-highest distinct salaries in an employee database.

21.1 Requirements

  • Create an employee table with IDs, names, departments, and salaries.
  • Insert at least ten employee records.
  • Include duplicate salaries to test tie handling.
  • Include a NULL salary to test missing-value handling.
  • Find the highest salary.
  • Find the second-highest and third-highest distinct salaries.
  • Return all employees at the second-highest salary.
  • Find the second-highest salary within each department.
  • Test a rank that does not exist.

21.2 Query 1: Highest Salary

SELECT MAX(salary) AS highest_salary
FROM employees;

21.3 Query 2: Second-Highest Distinct Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

21.4 Query 3: Third-Highest Distinct Salary

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 2;

21.5 Query 4: All Employees at the Second-Highest Salary

WITH ranked_employees AS (
    SELECT
        employee_id,
        employee_name,
        department,
        salary,
        DENSE_RANK() OVER (
            ORDER BY salary DESC
        ) AS salary_rank
    FROM employees
    WHERE salary IS NOT NULL
)
SELECT employee_id, employee_name, department, salary
FROM ranked_employees
WHERE salary_rank = 2;

21.6 Expected Learning Outcome

After completing the project, you should be able to select the appropriate ranking technique, handle duplicate values correctly, retrieve complete employee records, and explain the difference between value ranking and row numbering.

22. Practice Exercises

  1. Write a query to find the highest salary in the employees table.
  2. Write a query to find the second-highest distinct salary using MAX().
  3. Find the third-highest distinct salary using LIMIT and OFFSET.
  4. Use DENSE_RANK() to find employees with the fourth-highest distinct salary.
  5. Use ROW_NUMBER() to retrieve the fifth row when employees are sorted by salary.
  6. Return every employee earning the second-highest distinct salary.
  7. Find the second-highest distinct salary in each department.
  8. Find the third-highest distinct product price from a products table.
  9. Write a query that excludes NULL salary values.
  10. Test what happens when the requested rank is greater than the number of distinct salaries.

23. Interview Questions and Answers

Q1. What is the second-highest salary in SQL?

Answer: It is commonly the second-largest distinct salary value. It can be found using a subquery with MAX(), or with DISTINCT, ORDER BY, and LIMIT.

Q2. How do you find the second-highest salary using MAX()?

SELECT MAX(salary)
FROM employees
WHERE salary < (
    SELECT MAX(salary)
    FROM employees
);

Q3. How do you find the second-highest salary using LIMIT?

SELECT DISTINCT salary
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

Q4. What is the difference between RANK() and DENSE_RANK()?

Answer: Both assign the same rank to tied values. RANK() leaves gaps after ties, while DENSE_RANK() continues with the next consecutive rank.

Q5. What is the difference between ROW_NUMBER() and DENSE_RANK()?

Answer: ROW_NUMBER() gives every row a unique sequential number. DENSE_RANK() assigns the same rank to rows with equal ordered values.

Q6. How do you find the Nth-highest distinct salary?

Answer: Use DISTINCT with descending order and an offset of N-1, or use DENSE_RANK() and filter by the desired rank.

Q7. Why is DISTINCT important?

Answer: It removes duplicate values so repeated salaries do not occupy multiple positions in a distinct-value ranking.

Q8. How can you return all employees who receive the second-highest salary?

Answer: Find the second-highest distinct salary and filter employees whose salary equals that value, or use DENSE_RANK() and select rank 2.

Q9. What happens if the second-highest salary does not exist?

Answer: If the table has fewer than two distinct non-NULL salary values, the second-highest value cannot be found. A direct result-set query returns no rows; a scalar subquery returns NULL.

Q10. Can window functions be used in MySQL?

Answer: Yes. MySQL 8.0 and later support window functions such as ROW_NUMBER(), RANK(), and DENSE_RANK().

Q11. How do you find the second-highest salary in each department?

Answer: Use DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) and filter for rank 2.

Q12. Why should NULL values be handled explicitly?

Answer: NULL represents missing or unknown data. Filtering NULL values makes the ranking rule clear and prevents missing salaries from being treated as valid salary values.

Q13. What is OFFSET in MySQL?

Answer: OFFSET specifies how many rows to skip before returning rows. For the Nth row in a sorted list, the offset is N-1.

Q14. Which method is best for finding the Nth-highest distinct value?

Answer: For a single distinct value, DISTINCT with LIMIT and OFFSET is concise. For all records at a particular distinct rank, DENSE_RANK() is often more convenient.

Q15. How can you check the MySQL version?

SELECT VERSION();

24. Quick Revision Notes

  • Highest value: Use MAX(column_name).
  • Second-highest distinct value: Use MAX() with a less-than subquery or DISTINCT with LIMIT 1 OFFSET 1.
  • Nth-highest distinct value: Sort distinct values descending and use offset N-1.
  • ROW_NUMBER(): Assigns a unique number to every row.
  • RANK(): Assigns equal ranks to ties and leaves gaps.
  • DENSE_RANK(): Assigns equal ranks to ties without leaving gaps.
  • Duplicate values: Use DISTINCT or DENSE_RANK() when ranking distinct values.
  • NULL values: Use WHERE column_name IS NOT NULL when missing values should be excluded.
  • Department-wise ranking: Use PARTITION BY department.
  • MySQL compatibility: Window functions require MySQL 8.0 or later.
  • Missing rank: An Nth-highest value may not exist when there are fewer than N distinct non-NULL values.
  • Performance: Check indexes and query plans with realistic data before optimizing.

25. Best Practices Checklist

  • Clarify whether the requirement asks for a distinct value or the Nth row.
  • Use descending sorting when looking for highest values.
  • Use the correct offset: N-1.
  • Use DISTINCT when duplicate values must count only once.
  • Use DENSE_RANK() when all records at a particular distinct rank are needed.
  • Use a deterministic tie-breaker with ROW_NUMBER().
  • Handle NULL values according to the business requirement.
  • Test the query with duplicate values and small datasets.
  • Check the behavior when the requested rank does not exist.
  • Verify window-function compatibility with the MySQL server version.
  • Use EXPLAIN to inspect query performance when necessary.

26. Conclusion

Finding the second-highest and Nth-highest values in MySQL is an essential SQL skill used in database development, reporting, data analysis, and technical interviews. The best solution depends on the ranking requirement. MAX() with a subquery is a straightforward approach for the second-highest distinct value. DISTINCT with ORDER BY, LIMIT, and OFFSET provides a concise method for any fixed Nth-highest distinct value. Window functions such as DENSE_RANK(), RANK(), and ROW_NUMBER() are useful when ranking complete records or handling ties.

By practicing these methods with duplicate values, NULL values, department-wise ranking, and missing ranks, you can write more accurate SQL queries and confidently solve common MySQL interview problems.

Continue Learning: Explore the MySQL Training Course to strengthen your database skills, and register for a course demo to learn more.

whatsapp