Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Percentile calculation with a window function

I know you can get the average, total, min, and max over a subset of the data using a window function. But is it possible to get, say, the median, or the 25th percentile instead of the average with the window function?

Put another way, how do I rewrite this to get the id and the 25th or 50th percentile sales numbers within each district rather than the average?

SELECT id, avg(sales)
    OVER (PARTITION BY district) AS district_average
FROM t
like image 302
Stephen Smith Avatar asked Sep 25 '16 04:09

Stephen Smith


People also ask

How does SQL Server calculate percentile?

PERCENT_RANK() The PERCENT_RANK function in SQL Server calculates the relative rank SQL Percentile of each row. It always returns values greater than 0, and the highest value is 1. It does not count any NULL values.

How do you find the 75th percentile in Excel?

Enter the following formula into the cell, excluding quotes: "=PERCENTILE. EXC(A1:AX,k)" where "X" is the last row in column "A" where you have entered data, and "k" is the percentile value you are looking for.

How do you calculate the 75th percentile?

Arrange the numbers in ascending order and give the rank ranging from 1 to the lowest to 4 to the highest. Use the formula: 3=P100(4)3=P2575=P. Therefore, the score 30 has the 75 th percentile.


1 Answers

You can write this as an aggregation function using percentile_cont() or percentile_disc():

select district, percentile_cont(0.25) within group (order by sales)
from t
group by district;

Unfortunately, Postgres doesn't currently support these as a window functions:

select id, percentile_cont(0.25) within group (order by sales) over (partition by district) 
from t;

So, you can use a join:

select t.*, p_25, p_75
from t join
     (select district,
             percentile_cont(0.25) within group (order by sales) as p_25,
             percentile_cont(0.75) within group (order by sales) as p_75
      from t
      group by district
     ) td
     on t.district = td.district
like image 136
Gordon Linoff Avatar answered Sep 30 '22 15:09

Gordon Linoff