7

特定の変換を適用する必要がありますfn(argument)。ここでargumentは に等しいがvalue、負の場合はそうではない. 最初の負の値を取得するvalueと、連続した値で合計され、この合計が正になるまで「待機」します。それからあなたはそうしますfn(argument)。取得したいテーブルを参照してください。

値の引数
----------------------
  2 2      
  3 3      
 -10 0      
  4 0
  3 0
  10 7
  1 1

すべての値を合計して合計に適用fnするfnこともできますが、行ごとに異なる場合があり、具体的な fn を選択するには行番号を知ることが不可欠です。

Postgres SQL ソリューションが必要なため、ウィンドウ関数が適合するように見えますが、まだそれを行う式を書くのに十分な経験がありません。実際、残念ながら、私は「SQLで考える」のは初めてです。これは命令型の方法で簡単に実行できると思いますが、ストアド プロシージャはまだ書きたくありません。

4

2 に答える 2

27

私は遅れていると思いますが、これは誰かを助けるかもしれません:

select
    value,
    greatest(0, value) as argument
from your_table;
于 2015-02-13T16:47:24.097 に答える
2

これは、事前定義された集計関数のいずれにも実際には適合しません。あなたはおそらくあなた自身を書く必要があります。postgresqlでは、集計関数をウィンドウ関数として使用できることに注意してください。実際、9.0以降、C以外でウィンドウ関数を記述する唯一の方法です。

値の「合計」の状態を追跡する関数を作成できます。ただし、現在の「合計」が正の場合は常に入力値を返し、「合計」が負の場合は加算を続けます。次に、この合計またはゼロのいずれか大きい方をとる必要があります。聖霊降臨祭に:

-- 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);

これは、アグリゲートが入力として整数を受け取り、その状態を整数として格納することを定義します。

私はあなたの例をテーブルにコピーしました:

steve@steve@[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
steve@steve@[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
>> \.

そして、window句で集計関数を使用してこれらの値を生成できるようになりました。

steve@steve@[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)

ご覧のとおり、最後のステップは、関数が正またはゼロの場合に関数の出力を取得する必要があることです。これは、クエリをラップするか、それを行う関数を作成することで実行できます。

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

これにより、質問で指定した関数の引数が生成されます。

于 2011-08-13T16:47:44.323 に答える