SQL Practice Problem

Rank employees by salary

Medium Window Functions

Schema and sample data

Employees
emp_idnamesalary
1Ava Torres95000.00
2Ben Ncube82000.00
3Cara Singh82000.00
4Deng Liu71000.00
5Emma Rossi64000.00
Show setup SQL (copy to run)
CREATE TABLE Employees (
    emp_id INT PRIMARY KEY,
    name   VARCHAR(50) NOT NULL,
    salary DECIMAL(10,2) NOT NULL
);

INSERT INTO Employees (emp_id, name, salary) VALUES
(1, 'Ava Torres', 95000.00),
(2, 'Ben Ncube',  82000.00),
(3, 'Cara Singh', 82000.00),
(4, 'Deng Liu',   71000.00),
(5, 'Emma Rossi', 64000.00);
Your task

From the Employees table, return each employee's name, salary and a ranking column called salary_rank that ranks employees from the highest paid to the lowest paid. Use RANK() so that two employees on the same salary share a rank. Sort the output by salary_rank ascending, then by name.

Expected result

Your query should return
namesalarysalary_rank
Ava Torres95000.001
Ben Ncube82000.002
Cara Singh82000.002
Deng Liu71000.004
Emma Rossi64000.005
Show hint

This is a window function. Add RANK() OVER (ORDER BY salary DESC) as an extra column. The OVER clause defines the order in which rows are ranked without collapsing them into groups, so every employee row still comes back.

Try to write the query yourself before you open this.

Show solution and explanation
SELECT
    name,
    salary,
    RANK() OVER (ORDER BY salary DESC) AS salary_rank
FROM Employees
ORDER BY salary_rank, name;

RANK() OVER (ORDER BY salary DESC) is a window function: it assigns a number to every row based on the ordering inside the OVER clause, but unlike GROUP BY it does not fold rows together, so all five employees are still returned. The highest salary (95000) gets rank 1, the next distinct salary gets the next rank, and so on.

Ben Ncube and Cara Singh both earn 82000, so they tie and RANK() gives them the same rank of 2. The key behaviour to notice is what happens next: RANK() leaves a gap. Because two rows consumed positions 2 and 3, the following employee (Deng Liu) is ranked 4, not 3. The rank of a row equals one plus the number of rows that strictly outrank it. See the RANK function reference for more detail.

Contrast this with the two sibling functions. DENSE_RANK() also gives tied rows the same rank but does not leave a gap, so the sequence here would be 1, 2, 2, 3, 4. ROW_NUMBER() ignores ties entirely and hands every row a unique number (1, 2, 3, 4, 5), breaking the tie arbitrarily. A common mistake is reaching for ROW_NUMBER() when the question asks for a ranking, which silently gives one of the tied employees a better position than the other. For a side by side breakdown, read RANK vs DENSE_RANK vs ROW_NUMBER.

Keep practising

Work through more Medium exercises, or test yourself with the SQL interview questions.