2014-10-05 5 views
2

내 윈도우 함수 현재 그것에 대한 분석 쿼리의 하나 (예를 들어)이 될 것입니다 : 너희들은 아마 말할 수PostgreSQL을 쿼리 설계 문제 및 문제에 대한 나의 접근 방식이 불필요하게 복잡 여부에 대해 확실하지 직면 윈도우 함수

with intervals as (
    select 
    (select '09/27/2014'::date) + (n  || ' minutes')::interval start_time, 
    (select '09/27/2014'::date) + ((n+60) || ' minutes')::interval end_time 
     from generate_series(0, (24*60*7), 60 * 4) n 
) 
    select 
    extract(epoch from i.start_time)::numeric * 1000 as ts, 
    extract(epoch from i.end_time)::numeric * 1000 as end_ts, 
    sum(avg(messages.score)) over (order by i.start_time) as score 

    from messages 
    right join intervals i 
    on messages.timestamp >= i.start_time and messages.timestamp < i.end_time 

    where messages.timestamp between '09/27/2014' and '10/04/2014' 

    group by i.start_time, i.end_time 
    order by i.start_time 

-이 쿼리는 "점수"attribut의 평균을 계산 e와 주어진 시간 - 버킷 분포에 대한 메시지를 비교하고 그 옆에있는 버킷 (창을 사용)에 누적을 계산합니다.

다음은 각 버킷의 평균에 가장 가까운 상위 5 개 (예 : messages.text)를 찾는 것입니다. 나는 내 윈도우 함수를 사용하여 관련된 디자인으로 올라오고에 내 첫 번째 시도로 인해의 단계에서 불가피하게이를 내려 놓고 한

1) Join messages with the time-buckets 
2) Compute a score - avg(score) over (partition by start_time) as deviation and save it against each record of the joined relation 
3) Compute a rank() over (order by deviation) as rank 
4) Select where rank between 1 and 5 

그 이유에

는 바로 지금, 내가 가진 유일한 계획입니다 창 기능 (rank() over (partition by start_time, order by score - avg(score) over (partition by start_time)) 그리고 나는 그것이 작동 하는지를보기 위해 시도하지는 않았습니다.

내가 올바른 방향으로 가고 있는지에 대한 조언을 구할 수 있습니까?

+0

참고 :'generate_series을()'도 타임 스탬프와 함께 작동합니다. 'generate_series ('2014-09-27', '2014-10-04', '1 hour':: interval)'은 아마도 당신이 원하는 것을 할 것입니다. – wildplasser

+0

수정 :'generate_series ('2014-09-27 00:00:00', '2014-10-04 00:00:00', '1 hour':: interval)' – wildplasser

+0

@wildplasser 아, 네, 맞습니다 - 그건 훌륭한 리팩토링 제안입니다. 제가 해결할 것입니다!^_ ^ – Slania

답변

0

새끼에 - 여기에 내가 무엇을하고 작동하는 것 같다 : 비판 오픈 이제

을, 성능 최적화의 구조입니다 내 쿼리에서 중복 및 중복!^_^(마이너스 대신 직접 내가 결국 해결됩니다 모든 트위스트 간격 수학의 시계열을 생성!)

with intervals as (
    select 
     (select '09/29/2014'::date) + (n  || ' minutes')::interval start_time, 
     (select '09/29/2014'::date) + ((n+60) || ' minutes')::interval end_time 
     from generate_series(0, (24*60*7), 60 * 4) n 
), intervaled_messages as (
    select 
     extract(epoch from i.start_time)::numeric * 1000 as ts, 
     extract(epoch from i.end_time)::numeric * 1000 as end_ts, 
     abs(score - avg(score) over (partition by i.start_time)) as deviation 
    from messages 
    right join intervals i 
     on messages.timestamp >= i.start_time and messages.timestamp < i.end_time 
    where messages.timestamp between '09/29/2014' and '10/06/2014' 
), ranked_messages as (
    select ts, end_ts, deviation, 
    rank() over (partition by ts order by deviation) as rank, 
    row_number() over (partition by ts order by deviation) as row_number 
    from intervaled_messages 
) 
select ts, end_ts, deviation, rank 
from ranked_messages 
where rank between 1 and 5 
    and row_number between 1 and 5 
order by ts; 
0

(이 단지 내 제안이다) 제목해야 방향 :

  1. (모든 레코드 이상)의 평균 점수
  2. 작동 MINUS 받기

-- This will leave you with values also positive and negative

(row score, avg(score))
  1. 단계 2의 각 작업에 abs()을 사용하고, 같은 계산
  2. 사용 rank() 및 approprietly 위해 그들을
  3. WHERE rank BETWEEN 1 AND 5