2014-01-07 106 views
7

大多數數據庫都有內置函數用於計算中位數,但在Amazon Redshift中沒有看到任何中值。如何計算AWS 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

回答

5

,並作爲2014年10月17日,紅移支持MEDIAN窗函數:

# select min(median) from (select median(num) over() from temp); 
min 
----- 
4.0 
+0

更好的答案鏈接 – Keith

+0

從表中選擇不同的中位數(字段)() –

4

嘗試NTILE功能。

您會將您的數據分爲2個排名組,並從第一組中挑選最小值。這是因爲在具有奇數個數值的數據集中,第一個數字將比第二個數字多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 
+0

標記此爲接受的答案,因爲它看起來像它應該在理論工作,但我沒有實際測試過。好主意! – tayl0rs

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 
1

我也有這個困難,但得到了一些亞馬遜的幫助。自2014-06-30版本的Redshift以來,您可以使用PERCENTILE_CONTPERCENTILE_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)將選擇其中一個值。