Ich habe eine Tabelle mit zwei Spalten mit Permutationen / Kombinationen von ganzzahligen Arrays und eine dritte Spalte mit einem Wert wie folgt:
CREATE TABLE foo
(
perm integer[] NOT NULL,
combo integer[] NOT NULL,
value numeric NOT NULL DEFAULT 0
);
INSERT INTO foo
VALUES
( '{3,1,2}', '{1,2,3}', '1.1400' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0.9280' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,2,1}', '{1,2,3}', '0' ),
( '{3,2,1}', '{1,2,3}', '0.8000' )
Ich möchte den Durchschnitt und die Standardabweichung für jede Permutation sowie für jede Kombination herausfinden. Ich kann das mit dieser Abfrage machen:
SELECT
f1.perm,
f2.combo,
f1.perm_average_value,
f2.combo_average_value,
f1.perm_stddev,
f2.combo_stddev,
f1.perm_count,
f2.combo_count
FROM
(
SELECT
perm,
combo,
avg( value ) AS perm_average_value,
stddev_pop( value ) AS perm_stddev,
count( * ) AS perm_count
FROM foo
GROUP BY perm, combo
) AS f1
JOIN
(
SELECT
combo,
avg( value ) AS combo_average_value,
stddev_pop( value ) AS combo_stddev,
count( * ) AS combo_count
FROM foo
GROUP BY combo
) AS f2 ON ( f1.combo = f2.combo );
Diese Abfrage kann jedoch ziemlich langsam werden, wenn ich viele Daten habe, da die "foo" -Tabelle (die in Wirklichkeit aus 14 Partitionen mit jeweils ungefähr 4 Millionen Zeilen besteht) zweimal gescannt werden muss.
Kürzlich habe ich erfahren, dass Postgres "Fensterfunktionen" unterstützt, was im Grunde wie ein GROUP BY für eine bestimmte Spalte ist. Ich habe meine Abfrage so geändert, dass sie Folgendes verwendet:
SELECT
perm,
combo,
avg( value ) as perm_average_value,
avg( avg( value ) ) over w_combo AS combo_average_value,
stddev_pop( value ) as perm_stddev,
stddev_pop( avg( value ) ) over w_combo as combo_stddev,
count( * ) as perm_count,
sum( count( * ) ) over w_combo AS combo_count
FROM foo
GROUP BY perm, combo
WINDOW w_combo AS ( PARTITION BY combo );
Während dies für die Spalte "combo_count" funktioniert, sind die Spalten "combo_average_value" und "combo_stddev" nicht mehr korrekt. Es scheint, dass der Durchschnitt für jede Permutation genommen und dann für jede Kombination ein zweites Mal gemittelt wird, was falsch ist.
Wie kann ich das beheben? Können Fensterfunktionen hier überhaupt als Optimierung verwendet werden?