# 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..