2011-01-12 5 views
1

누적 빈도 데이터를 데이터베이스에서 얻으려고합니다. 우리가 본 고유 한 상태 업데이트 횟수와 상태 업데이트 양을 가진 사용자 수를 가진 간단한 임시 테이블을 만들었습니다.SQL : Fast 누적 빈도 쿼리 (포스트 그레스)

select statuses_count, frequency/(select * from total_statuses)::float, (select sum(frequency)/(select * from total_statuses)::float AS percentage from statuses_count_tmp WHERE statuses_count <= SCT.statuses_count) AS cumulative_percent FROM statuses_count_tmp AS SCT ORDER BY statuses_count DESC; 

하지만이 꽤 걸리는 쿼리의 수가 매우 빠르게 성장 :

 Table "pg_temp_4.statuses_count_tmp" 
    Column  | Type | Modifiers 
----------------+---------+----------- 
statuses_count | integer | 
frequency  | bigint | 
Indexes: 
    "statuses_count_idx" UNIQUE, btree (statuses_count) 

나의 현재 쿼리입니다. 그래서 ~ 50,000 행을 가지고, 나는 읽어야 할 50k 계승 행을보고 있습니다. 여기에 앉아서 쿼리를 보면서 갈아 가며 나는 아직 끝나지 않은 더 나은 솔루션을 원합니다.

이런 식으로 뭔가를 얻을 수 있었으면 :

0  0.26975161  0.26975161 
1  0.15306534  0.42281695 
2  0.05513516  0.47795211 
3  0.03050646  0.50845857 
4  0.02064444  0.52910301 

답변

2

은 윈도우 기능을 풀수있을 경우, 나중에 PostgreSQL을 8.4 이상이 가정. 나는 total_statusesselect sum(frequency) from statuses_count_tmp의 행을 따라보기 또는 임시 테이블이라고 추측하고 있습니까?

: 당신의 최선의 방법은 반복적으로 데이터를 처리하는 것입니다 8.4의 윈도우 함수없이

with total_statuses as (select sum(frequency) from statuses_count_tmp) 
select statuses_count, 
     frequency/(select * from total_statuses) as frequency, 
     sum(frequency) over(order by statuses_count) 
     /(select * from total_statuses) as cumulative_frequency 
from statuses_count_tmp 

: 나는 명령문의 기간 동안 한 번만 결과를 계산해야하는 여기 CTE로 썼다

create type cumulative_sum_type as (statuses_count int, frequency numeric, cumulative_frequency numeric); 
create or replace function cumulative_sum() returns setof cumulative_sum_type strict stable language plpgsql as $$ 
declare 
    running_total bigint := 0; 
    total bigint; 
    data_in record; 
    data_out cumulative_sum_type; 
begin 
    select sum(frequency) into total from statuses_count_tmp; 
    for data_in in select statuses_count, frequency from statuses_count_tmp order by statuses_count 
    loop 
    data_out.statuses_count := data_in.statuses_count; 
    running_total := running_total + data_in.frequency; 
    data_out.frequency = data_in.frequency::numeric/total; 
    data_out.cumulative_frequency = running_total::numeric/total; 
    return next data_out; 
    end loop; 
end; 
$$; 
select * from cumulative_sum(); 
+0

아, 그런 행운은 없습니다. 8.3.9 그리고 앞으로 며칠 안에 그것을 업데이트 할 실제의 희망은 없지만 일단 업데이트가되면이 솔루션을 염두에 두겠습니다. – Peck

+0

+1 거의 동일한 대답을 썼습니다. –

+0

@Peck : plpgsql 함수를 사용하여 8.3에서 작동하는 솔루션을 추가했습니다. – araqnid