18

テーブル内のさまざまなディメンションのパーセンテージを計算する必要があります。ウィンドウ関数を使用して分母を計算することで物事を単純化したいのですが、分子も集計でなければならないため、問題が発生しています。

簡単な例として、次の表を取り上げます。

create temp table test (d1 text, d2 text, v numeric);
insert into test values ('a','x',5), ('a','y',5), ('a','y',10), ('b','x',20);

d1 から個々の行のシェアを計算したいだけの場合、ウィンドウ関数は正常に機能します。

select d1, d2, v/sum(v) over (partition by d1)
from test;

"b";"x";1.00
"a";"x";0.25
"a";"y";0.25
"a";"y";0.50

ただし、d1 から d2 の合計の全体的なシェアを計算する必要があります。私が探している出力はこれです:

"b";"x";1.00
"a";"x";0.25
"a";"y";0.75

だから私はこれを試します:

select d1, d2, sum(v)/sum(v) over (partition by d1)
from test
group by d1, d2;

ただし、エラーが発生するようになりました。

ERROR:  column "test.v" must appear in the GROUP BY clause or be used in an aggregate function

これは、グループ化句でウィンドウ関数が考慮されていないと不平を言っているためだと思いますが、ウィンドウ化関数をグループ化句に入れることはできません。

これは、Postgresql 8.4 のフォークであり、同じウィンドウ機能を共有する Greenplum 4.1 を使用しています。Greenplum は相関サブクエリを実行できないことに注意してください。

4

2 に答える 2

30

私はあなたがこれを探していると思います:

SELECT d1, d2, sum(v)/sum(sum(v)) OVER (PARTITION BY d1) AS share
FROM   test
GROUP  BY d1, d2;

要求された結果を生成します。

ウィンドウ関数は、集計関数の後に適用されます。外側のsum()insum(sum(v)) OVER ...はウィンドウ関数 (付属OVER ...節) であり、内側sum()は集約関数です。

事実上、次と同じです。

WITH x AS (
   SELECT d1, d2, sum(v) AS sv
   FROM   test
   GROUP  BY d1, d2
   )
SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM   x;

または(CTEなし):

SELECT d1, d2, sv/sum(sv) OVER (PARTITION BY d1) AS share
FROM  (
   SELECT d1, d2, sum(v) AS sv
   FROM   test
   GROUP  BY d1, d2
   ) x;

または@Muのバリアント。

余談ですが、Greenplum はバージョン 4.2 で相関サブクエリを導入しました。リリースノートを参照してください。

于 2011-12-15T17:35:43.903 に答える
2

ウィンドウ関数ですべてを行う必要がありますか? 得られた結果をグループ化し、合計を合計する必要があるようにd1思えd2ます。

select d1, d2, sum(p)
from (
    select d1, d2, v/sum(v) over (partition by d1) as p
    from test
) as dt
group by d1, d2

それは私にこれを与えます:

 d1 | d2 |          sum           
----+----+------------------------
 a  | x  | 0.25000000000000000000
 a  | y  | 0.75000000000000000000
 b  | x  | 1.00000000000000000000
于 2011-12-15T06:51:44.743 に答える