복붙노트

[SQL] 어떻게 포스트 그레스에 이동 평균 지수를 계산?

SQL

어떻게 포스트 그레스에 이동 평균 지수를 계산?

나는 포스트 그레스에 지수 이동 평균 (EMA)를 구현하기 위해 노력하고있어,하지만 난 설명서를 확인하고 그것에 대해 생각하는 더 나는 더 나는 혼란보십시오.

EMA (X)의 화학식이다 :

EMA(x1) = x1
EMA(xn) = α * xn + (1 - α) * EMA(xn-1)

여기에 수행해야합니다 정확히 무엇을 마지막으로 계산 된 요소의 결과를 유지, 애그리 게이터 (aggregator)에 대한 완벽한 것 같다. 그러나 애그리 게이터 (aggregator)은 하나 개의 결과를 생성합니다 (로 축소, 또는 배) 여기에서 우리는 (맵으로) 결과 목록 (열)가 필요합니다. 내가 어떻게 프로 시저 및 함수 작업을 확인되었지만, AFAIK 그들은 하나 개의 출력이 아닌 열을 생산하고 있습니다. 나는 프로 시저 및 함수를 많이 봐 왔지만,이 같은 일을 특히 정말, 관계 대수이 상호 작용을하지 어떻게 EMA를 알아낼 수 없습니다.

나는 운이 지금까지 Internets 검색이 없었다. 그러나 EMA에 대한 정의는 내가이되는 NoSQL로 이동하는 내 상황에서 과도한 될 것입니다 때문에 포스트 그레스의 작품은, 간단하고 효율적이다 무언가로이 정의를 번역 할 수 있습니다 희망, 매우 간단합니다.

감사합니다.

PD : 여기에 당신은 예를 볼 수 있습니다 https://docs.google.com/spreadsheet/ccc?key=0AvfclSzBscS6dDJCNWlrT3NYdDJxbkh3cGJ2S2V0cVE

해결법

  1. ==============================

    1.당신은 당신의 자신의 집계 함수를 정의하고 각 단계가 아니라 하나의 값으로 집계 출력을 얻을 수있는 창 사양을 사용할 수 있습니다.

    당신은 당신의 자신의 집계 함수를 정의하고 각 단계가 아니라 하나의 값으로 집계 출력을 얻을 수있는 창 사양을 사용할 수 있습니다.

    따라서 집합 상태의 피스이고, 각 행에 대해 그 상태를 변경하는 함수를 변환하고, 임의로 마무리 함수 출력값로 상태 변환. 이 같은 간단한 경우에, 단지 기능이 충분해야 변환.

    create function ema_func(numeric, numeric) returns numeric
      language plpgsql as $$
    declare
      alpha numeric := 0.5;
    begin
      -- uncomment the following line to see what the parameters mean
      -- raise info 'ema_func: % %', $1, $2;
      return case
                  when $1 is null then $2
                  else alpha * $2 + (1 - alpha) * $1
             end;
    end
    $$;
    create aggregate ema(basetype = numeric, sfunc = ema_func, stype = numeric);
    

    어느 날 준다 :

    steve@steve@[local] =# select x, ema(x, 0.1) over(w), ema(x, 0.2) over(w) from data window w as (order by n asc) limit 5;
         x     |      ema      |      ema      
    -----------+---------------+---------------
     44.988564 |     44.988564 |     44.988564
       39.5634 |    44.4460476 |    43.9035312
     38.605724 |   43.86201524 |   42.84396976
     38.209646 |  43.296778316 |  41.917105008
     44.541264 | 43.4212268844 | 42.4419368064
    

    이 숫자는 질문에 추가 스프레드 시트에 일치하는 것.

    또한, 당신은 문에서 매개 변수로 알파를 전달하는 기능을 정의 할 수 있습니다 :

    create or replace function ema_func(state numeric, inval numeric, alpha numeric)
      returns numeric
      language plpgsql as $$
    begin
      return case
             when state is null then inval
             else alpha * inval + (1-alpha) * state
             end;
    end
    $$;
    
    create aggregate ema(numeric, numeric) (sfunc = ema_func, stype = numeric);
    
    select x, ema(x, 0.5 /* alpha */) over (order by n asc) from data
    

    당신이 그 중 하나의 이름으로 매개 변수를 참조 할 수 있지만 또한,이 기능은, 실제로는 전혀 plpgsql에있을 필요는 없지만 단지 SQL 함수가 될 수 있도록 간단합니다 :

    create or replace function ema_func(state numeric, inval numeric, alpha numeric)
      returns numeric
      language sql as $$
    select case
           when $1 is null then $2
           else $3 * $2 + (1-$3) * $1
           end
    $$;
    
  2. ==============================

    2.이 유형의 쿼리는 재귀 CTE로 해결 될 수 - 시도 :

    이 유형의 쿼리는 재귀 CTE로 해결 될 수 - 시도 :

    with recursive cte as (
    select n, x ema from my_table where n = 1
    union all
    select m.n, alpha * m.x + (1 - alpha) * cte.ema
    from cte
    join my_table m on cte.n = m.n - 1
    cross join (select ? alpha) a)
    select * from cte;
    
  3. ==============================

    3.

    --$1 Stock code
    --$2 exponential;
    create or replace function fn_ema(text,numeric)
        returns numeric as
        $body$
        declare
            alpha numeric := 0.5;
            var_r record;
            result numeric:=0;
            n int;
            p1 numeric;
        begin
            alpha=2/(1+$2);
            n=0;
            for var_r in(select *
            from stock_old_invest
            where code=$1  order by stock_time desc)
            loop
                if n>0 then
                    result=result+(1-alpha)^n*var_r.price_now;
                else 
                    p1=var_r.price_now;
                end if;
                n=n+1;
            end loop;
            result=alpha*(result+p1);
            return result;
        end
        $body$
        language plpgsql volatile
        cost 100;
        alter function fn_ema(text,numeric)
        owner to postgres;
    
  4. from https://stackoverflow.com/questions/8871426/how-to-calculate-an-exponential-moving-average-on-postgres by cc-by-sa and MIT license