PostgreSQL에서 누적 합계 계산


85

필드의 누적 또는 실행 양을 찾아 스테이징에서 테이블로 삽입하고 싶습니다. 내 스테이징 구조는 다음과 같습니다.

ea_month    id       amount    ea_year    circle_id
April       92570    1000      2014        1
April       92571    3000      2014        2
April       92572    2000      2014        3
March       92573    3000      2014        1
March       92574    2500      2014        2
March       92575    3750      2014        3
February    92576    2000      2014        1
February    92577    2500      2014        2
February    92578    1450      2014        3          

내 대상 테이블이 다음과 같이 보이기를 원합니다.

ea_month    id       amount    ea_year    circle_id    cum_amt
February    92576    1000      2014        1           1000 
March       92573    3000      2014        1           4000
April       92570    2000      2014        1           6000
February    92577    3000      2014        2           3000
March       92574    2500      2014        2           5500
April       92571    3750      2014        2           9250
February    92578    2000      2014        3           2000
March       92575    2500      2014        3           4500
April       92572    1450      2014        3           5950

이 결과를 달성하는 방법에 대해 정말 혼란 스럽습니다. PostgreSQL을 사용하여이 결과를 얻고 싶습니다.

누구든지이 결과 세트를 달성하는 방법을 제안 할 수 있습니까?


1
대상 테이블에서 cum_amount 1000을 어떻게 얻습니까? circle_id의 경우 금액은 2000 인 것 같습니다.

답변:


130

기본적으로 창 기능 이 필요 합니다 . 그것은 오늘날 표준 기능입니다. 정품 창 함수 외에도 절 을 추가하여 Postgres에서 모든 집계 함수를 창 함수로 사용할 수 있습니다 OVER.

여기서 특별한 어려움은 파티션과 정렬 순서를 올바르게 얻는 것입니다.

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id
                         ORDER BY ea_year, ea_month) AS cum_amt
FROM   tbl
ORDER  BY circle_id, month;

그리고 아니 GROUP BY .

각 행의 합계는 파티션의 첫 번째 행에서 현재 행까지 계산되거나 정확한 매뉴얼 을 인용 합니다 .

기본 프레임 옵션은 RANGE UNBOUNDED PRECEDING동일하다, RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. 를 사용 하면 파티션의 모든 행이 현재 행의 마지막 피어 까지 시작ORDER BY 되도록 프레임을 설정합니다 .ORDER BY

... 그것은 당신이 추구하는 누적 또는 누적 합계입니다. 대담하게 강조합니다.

이 쿼리에서 동일한 행 (circle_id, ea_year, ea_month)"동료" 입니다. 이들 모두는 합계에 모든 피어가 추가 된 동일한 누적 합계를 보여줍니다. 그러나 테이블이 UNIQUEon 이라고 가정 (circle_id, ea_year, ea_month)하면 정렬 순서가 결정적이며 행에 피어가 없습니다.

이제 ORDER BY ... ea_month 월 이름의 문자열에서는 작동하지 않습니다 . Postgres는 로케일 설정에 따라 알파벳순으로 정렬합니다.

date테이블에 실제 값이 저장되어 있으면 적절하게 정렬 할 수 있습니다. 그렇지 않으면, 나는 대체하는 것이 좋습니다 ea_yearea_month단일 컬럼 mon유형의 date테이블입니다.

  • 당신이 가진 것을 변화 시키십시오 to_date():

      to_date(ea_year || ea_month , 'YYYYMonth') AS mon
    
  • 표시를 위해 다음을 사용하여 원본 문자열을 얻을 수 있습니다 to_char().

      to_char(mon, 'Month') AS ea_month
      to_char(mon, 'YYYY') AS ea_year
    

불행한 디자인을 고수하는 동안 다음과 같이 작동합니다.

SELECT ea_month, id, amount, ea_year, circle_id
     , sum(amount) OVER (PARTITION BY circle_id ORDER BY mon) AS cum_amt
FROM   (SELECT *, to_date(ea_year || ea_month, 'YYYYMonth') AS mon FROM tbl)
ORDER  BY circle_id, mon;

해결 해주셔서 감사합니다 .. 한 가지 더 도와 주실 수 있나요? 커서를 사용하여 동일한 것을 구현하고 싶습니다. 논리는 모든 원이 1 년에 한 달 동안 하나의 레코드 만 가질 것입니다. 그리고이 기능은 매달 한 번 실행되어야합니다. 어떻게하면 되나요?
Yousuf Sultan 2014

4
@YousufSultan : 대부분의 경우 커서보다 더 나은 솔루션이 있습니다. 그것은 확실히 새로운 질문에 대한 것입니다. 새로운 질문을 시작하십시오.
Erwin Brandstetter 2014-04-04

나는이 대답이 불완전하다는 것을 적어도 여기에 "프레임"이 있고 기본값 range unbounded precedingrange between unbounded preceding and current row. 이것이 sum()윈도우 함수로 사용될 때 누계를 생성하는 이유입니다. 반면 다른 윈도우 함수에는이 기본 프레임이 없습니다.
Colin 't Hart

1
@ Colin'tHart : 명확히하기 위해 위에 몇 가지를 더 추가했습니다.
Erwin Brandstetter 2016

다음은 더 간단한 쿼리로 유사한 질문에 대한 링크입니다 ( PARTITION누계를 생성하는 데 항상 필요한 것은 아닙니다). stackoverflow.com/a/5700744/175830
Jason Axelson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.