2011-08-13 7 views
3

特定の変換fn(argument)を適用する必要があります。ここではargumentvalueに等しいが、否定的ではない。最初の否定valueが得られたら、それは連続する値と合計してこの合計が正になるまで「待機」します。次に、fn(argument)を実行します。私が取得したい表を参照してください。Postgres SQLで正の集計値を選択し、負の値を無視する

 
value  argument 
--------------------- 
    2   2  
    3   3  
-10   0  
    4   0 
    3   0 
    10   7 
    1   1 

私はすべての値を合計し、合計にfnを適用されますが、fnは異なる行のために異なることができ、具体的なFNを選択するために行番号を知ることが不可欠であることができました。

Postgres SQLソリューションが必要なので、ウィンドウ関数のように見えますが、まだそれを行う式を書くのに十分な経験はありません。実際、私は残念なことに "SQLで考える"のが新しいです。私は簡単な方法で簡単にやり遂げることができると思いますが、ストアドプロシージャをまだ作成したくありません。

+1

はあなたが探しているの文の結果の一例を与えることができますか?私はあなたの正確な目標が何であるか分かりません。 – migu

+0

入力は値と対応するfnsです。私。 (fn、value)のような行そして、私は上記の規則に基づいて実際のfn引数を計算しなければなりません。編集:笑、私はこの応答を書いたように、入力説明を求めるinititalのコメントは消えてしまった。 – zamza

+0

migu、結果は質問に記載されています。入力は値だけです、私は引数を計算する必要があります。 – zamza

答えて

1

これはあらかじめ定義された集約関数のいずれにも当てはまりません。あなたはおそらく自分で書く必要があります。 postgresqlでは、集計関数をウィンドウ関数として使用することができ、実際には9.0以外のC言語でウィンドウ関数を書く唯一の方法であることに注意してください。

現在の "sum"が正の場合は常に入力値を返し、 "sum"が負の場合は加算を継続する点を除いて、値を "合計"する状態を追跡する関数を書くことができます。次に、この合計かゼロのどちらか大きい方を取るだけです。聖霊降臨祭のために:あなたはこのアキュムレータを呼び出すために集約関数を作成する必要が

-- accumulator function: first arg is state, second arg is input 
create or replace function ouraggfunc(int, int) 
returns int immutable language plpgsql as $$ 
begin 
    raise info 'ouraggfunc: %, %', $1, $2; -- to help you see what's going on 
    -- get started by returning the first value ($1 is null - no state - first row) 
    if $1 is null then 
    return $2; 
    end if; 
    -- if our state is negative, we're summing until it becomes positive 
    -- otherwise, we're just returning the input 
    if $1 < 0 then 
    return $1 + $2; 
    else 
    return $2; 
    end if; 
end; 
$$; 

を:

create aggregate ouragg(basetype = int, sfunc = ouraggfunc, stype = int); 

これは、集約は、入力として整数を取り、整数としてその状態を保存することが規定されています。

私はテーブルにあなたの例をコピー:、あなたが見ることができるように

[email protected]@[local] =# select value, argument, ouragg(value) over(order by id) from t; 
INFO: ouraggfunc: <NULL>, 2 
INFO: ouraggfunc: 2, 3 
INFO: ouraggfunc: 3, -10 
INFO: ouraggfunc: -10, 4 
INFO: ouraggfunc: -6, 3 
INFO: ouraggfunc: -3, 10 
INFO: ouraggfunc: 7, 1 
value | argument | ouragg 
-------+----------+-------- 
    2 |  2 |  2 
    3 |  3 |  3 
    -10 |  0 | -10 
    4 |  0 |  -6 
    3 |  0 |  -3 
    10 |  7 |  7 
    1 |  1 |  1 
(7 rows) 

[email protected]@[local] =# create table t(id serial primary key, value int not null, argument int not null); 
NOTICE: CREATE TABLE will create implicit sequence "t_id_seq" for serial column "t.id" 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "t_pkey" for table "t" 
CREATE TABLE 
[email protected]@[local] =# copy t(value, argument) from stdin; 
Enter data to be copied followed by a newline. 
End with a backslash and a period on a line by itself. 
>> 2 2 
>> 3 3 
>> -10 0 
>> 4 0 
>> 3 0 
>> 10 7 
>> 1 1 
>> \. 

そして、あなたが今、ウィンドウ句で集約関数を用いて製造されたこれらの値を持つことができます最後のステップは、関数が正またはゼロの場合は関数の出力を取る必要があるということです。これは、クエリをラップする、またはそれを行うための機能を記述することによって行うことができます。

create function positive(int) returns int immutable strict language sql as 
$$ select case when $1 > 0 then $1 else 0 end $$; 

となりました:

select value, argument, positive(ouragg(value) over(order by id)) as raw_agg from t 

これは、あなたが質問で指定された関数の引数を生成します。

+0

最大値(0、0)はNuo Rafael Figueiredoが言ったように十分です – Controlix

+0

いいえ、それは指定されたOPの結果を生成しません – araqnid

10

は、私が遅刻としたが、これは、誰かが助けるかもしれない:

select 
    value, 
    greatest(0, value) as argument 
from your_table; 
関連する問題