AggregateSQL standard

PERCENTILE_CONT

Finds the median or another percentile — the value below which a given share of the data lies.

Syntax

PERCENTILE_CONT(<fraction>) WITHIN GROUP (ORDER BY <expression>)

PERCENTILE_CONT(0.5) is the median: half the values are smaller, half are larger. Unlike the average, a single very large value doesn't shift it. The function can return a number between two existing ones; if you need exactly one of the existing values, use PERCENTILE_DISC.

Data for the examples

employees

namedepartmentsalarybonusphone
Emmabackend1200300+44 7700 900123
Liambackend1000NULLNULL
Oliviafrontend1350150+44 7700 900456
Noahfrontend950NULL+44 7700 900789
Sophiadesign1200200NULL

orders

idcreated_atamount
12026-07-03 10:15:00120.50
22026-07-28 18:40:0080.25
32026-08-09 09:05:00199.99
42026-08-21 14:30:0045.00
52026-09-02 11:00:0064.75

These tables already exist in the sandbox — the examples below use them. Want to try this in your own database? Copy the SQL.

The median salary
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary
FROM employees;
median_salary
1200
Median versus average
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median,
ROUND(AVG(amount), 2) AS average
FROM orders;
medianaverage
80.25102.10

The 199.99 order pulls the average up, while the median stays a “typical” amount.

Several percentiles at once
SELECT PERCENTILE_CONT(ARRAY[0.25, 0.5, 0.75]) WITHIN GROUP (ORDER BY salary) AS quartiles
FROM employees;
quartiles
[1000,1200,1200]

An array of fractions gives an array of answers: for a quarter, a half and three quarters.

Watch out

The syntax is unusual: the fraction goes in the function's brackets, and the column in WITHIN GROUP (ORDER BY …). PERCENTILE_CONT(salary, 0.5) throws WITHIN GROUP is required for ordered-set aggregate.

The fraction runs from 0 to 1, not in percent: the 90th percentile is 0.9, and 90 throws percentile value 90 is not between 0 and 1.

PERCENTILE_CONT only works with numbers and intervals — for dates and text, use PERCENTILE_DISC. And it can't be a window function with OVER: OVER is not supported for ordered-set aggregate.

Related functions

Learn more in the course