大多数数据库都有内置函数来计算中位数但我在Amazon Redshift中没有看到任何中位数。
您可以使用nth_value()和count()分析函数的组合来计算中值,但这似乎很笨拙。如果分析数据库没有内置计算中位数的方法,我会很惊讶,所以我假设我错过了一些东西。
http://docs.aws.amazon.com/redshift/latest/dg/r_Examples_of_NTH_WF.html http://docs.aws.amazon.com/redshift/latest/dg/c_Window_functions.html
答案 0 :(得分:5)
截至2014-10-17,Redshift支持MEDIAN窗口功能:
# select min(median) from (select median(num) over () from temp);
min
-----
4.0
答案 1 :(得分:4)
尝试NTILE功能。
您可以将数据划分为2个排名组,并从第一组中选择最小值。这是因为在具有奇数个值的数据集中,第一个ntile将比第二个具有多1个值。这种近似应该适用于大型数据集。
create table temp (num smallint);
insert into temp values (1),(5),(10),(2),(4);
select num, ntile(2) over(order by num desc) from temp ;
num | ntile
-----+-------
10 | 1
5 | 1
4 | 1
2 | 2
1 | 2
select min(num) as median from (select num, ntile(2) over(order by num desc) from temp) where ntile = 1;
median
--------
4
答案 2 :(得分:1)
我也遇到了这个困难,但得到了亚马逊的一些帮助。自2014-06-30版本的Redshift以来,您可以使用PERCENTILE_CONT或PERCENTILE_DISC窗口函数执行此操作。
它们使用起来有点奇怪,因为它们会将每个行的中位数(或您选择的任何百分位数)固定。你把它放在一个子查询中,然后取中间列的MIN(或其他)。
# select count(num), min(median) as median
from
(select num, percentile_cont (0.5) within group (order by num) over () as median from temp);
count | median
-------+--------
5 | 4.0
(它之所以复杂,是因为窗口函数也可以自己进行迷你分组,并命令一次性给出许多组的中位数,以及其他技巧。)
在偶数个值的情况下,CONT(inuous)将在两个中间值之间进行插值,其中DISC(rete)将选择其中一个值。
答案 3 :(得分:0)
如果我正在寻找足够接近的答案,我通常会使用NTILE函数将数据拆分为两组。但是,如果我想要精确的中位数(例如偶数行的中点),我会使用AWS Redshift Discussion Forum上建议的技术。
此技术按升序和降序对行进行排序,然后如果有奇数行,则返回中间行的平均值(即row_num_asc = row_num_desc),这只是中间行本身
CREATE TABLE temp (num SMALLINT);
INSERT INTO temp VALUES (1),(5),(10),(2),(4);
SELECT
AVG(num) AS median
FROM
(SELECT
num,
SUM(1) OVER (ORDER BY num ASC) AS row_num_asc,
SUM(1) OVER (ORDER BY num DESC) AS row_num_desc
FROM
temp) AS ordered
WHERE
row_num_asc IN (row_num_desc, row_num_desc - 1, row_num_desc + 1);
median
--------
4
如果有偶数行,则返回两个中间行的平均值。
INSERT INTO temp VALUES (9);
SELECT
AVG(num) AS median
FROM
(SELECT
num,
SUM(1) OVER (ORDER BY num ASC) AS row_num_asc,
SUM(1) OVER (ORDER BY num DESC) AS row_num_desc
FROM
temp) AS ordered
WHERE
row_num_asc IN (row_num_desc, row_num_desc - 1, row_num_desc + 1);
median
--------
4.5