# Calculating Percentile (and Median) in PostgreSQL

Modern versions of PostgreSQL (≥ 9.4) make it easy to calculate the percentile for a list of values at any percentage using the `percentile_cont` and `percentile_disc` ordered-set aggregation functions.

The two functions work very similarly, but differ in how they merge the final result:

• `percentile_disc` will return a value from the input set closest to the percentile you request
• `percentile_cont` will return an interpolated value between multiple values based on the distribution. You can think of this as being more accurate, but can return a fractional value between the two values from the input

In these examples we'll imagine we have a table called `things` with a column called `value`.

## Calculating The Median

The median is generally the 50th percentile. You can calculate it with the following query:

``````select percentile_disc(0.5) within group (order by value)
from things```
```

The `within group` syntax is called an ordered-set aggregate

For a percentile that lies between values from the input, use `percentile_cont` to get the interpolated result:

``````select percentile_const(0.5) within group (order by value)
from things```
```

## Calculating A Perentile

Any percentile can be calculated by providing a fractional amount from 0 to 1. The percentile function can be used multiple times within the query:

``````select
percentile_disc(0.25) within group (order by value),
percentile_disc(0.5) within group (order by value),
percentile_disc(0.75) within group (order by value)
from things```
```

`within group` can be used with other claues like `group by`. Here’s an example where different percentiles are calculated for numbers less than 100, and everything else.

``````select
value < 100 as less_than_100,
percentile_disc(0.75) within group (order by value)
from things
group by 1```
```

`group by 1` groups by the first expression in the select statement

## Calculating All Percentiles

You can easily calculate all percentiles using `generate_series`. In this example, every percentile from 1 to 100 is returned as individual rows:

``````select k, percentile_disc(k) within group (order by value)
from things, generate_series(0.01, 1, 0.01) as k
group by k```
```

`generate_series` generates table values between a starting an ending value, with an optional step. In this example, it returns `0.01`, `0.02`, etc..