viele Felder addieren

Guten Morgen pg-forum, hier mein erster Eintrag:
Meine Tabelle hat 365 nummerischen Felder (Feldnamen: v001 bis v366).
Das Abfrageergebnis soll ebenfalls 366 Felder haben (Ziel-Feldnamen: s001 bis s366),
wobei alle Ziel-Felder aus Summen der Input-Felder bestehen, nach folgendem Muster
s001 = v001
s002 = v001 + v002
s003 = v001 + v002 + v003

Ich löse das derzeit wie folgt:
SELECT
v001 AS s001,
v001 + v002 AS s002,
v001 + v002 + v003 AS s003
FROM mytable;

also sehr umständlich und bei 366 Feldern wird das auch ein gewaltig langer SQL string.
Gibt es einer eleganteren Lösung?
Vielen Dank.

Das klingt nach FAIL-Design. 365 - zufällig hat ein Jahr so viele Tage - du hast für jeden Tag eine Spalte, oder?

Bring das in ein gescheites Modell - oder erkläre uns, warum Du das so machst.

Danke für die rasche Antwort akretschmer.
Was bitte ist FAIL-Design?
366: genau, eine Spalte für jeden Tag (berücksichtigt Schaltjahre).
Hintergrund:
Die Tabelle enthält tägliche Niederschlagsmessungen für rund 4000 Messstationen und 40 Jahre.
Die Tabelle enthält also zusätzlich zu den 366 für die Tageswerte noch eine Spalte für StationsID und Jahr.
Dieses Tabellendesign vermeidet also Redundanz, da dien Spalte für julianday entfällt.

FAIL? Kommt aus dem englischen.

Besser wäre etwa folgendes Design:

test=# create table regen(station int, datum date, menge int, primary key(station, datum));

Dann kannst Du auch via Window-Funktionen die mengen zusammenrechnen.

test=*# insert into regen select *, (random() * 20)::int as menge from (select * from generate_Series(1,3) station) s crossjoin (select '2014-01-01'::date + x * '1day'::interval as datum from generate_series(1,7)x)x;
INSERT 0 21
Time: 1,319 ms
test=*# select * from regen;
 station |   datum    | menge
---------+------------+-------
       1 | 2014-01-02 |    10
       1 | 2014-01-03 |    20
       1 | 2014-01-04 |    16
       1 | 2014-01-05 |    17
       1 | 2014-01-06 |     3
       1 | 2014-01-07 |    11
       1 | 2014-01-08 |     4
       2 | 2014-01-02 |    10
       2 | 2014-01-03 |     4
       2 | 2014-01-04 |    17
       2 | 2014-01-05 |    18
       2 | 2014-01-06 |     1
       2 | 2014-01-07 |     9
       2 | 2014-01-08 |    18
       3 | 2014-01-02 |    10
       3 | 2014-01-03 |     4
       3 | 2014-01-04 |    14
       3 | 2014-01-05 |     8
       3 | 2014-01-06 |    16
       3 | 2014-01-07 |     7
       3 | 2014-01-08 |     1
(21 rows)

Nun mal je Station die Summen von Anfang bis zum aktuellen Tag:

test=*# select *, sum(menge) over (partition by station order by datum) as summe_bis_hier from regen;
 station |   datum    | menge | summe_bis_hier
---------+------------+-------+----------------
       1 | 2014-01-02 |    10 |             10
       1 | 2014-01-03 |    20 |             30
       1 | 2014-01-04 |    16 |             46
       1 | 2014-01-05 |    17 |             63
       1 | 2014-01-06 |     3 |             66
       1 | 2014-01-07 |    11 |             77
       1 | 2014-01-08 |     4 |             81
       2 | 2014-01-02 |    10 |             10
       2 | 2014-01-03 |     4 |             14
       2 | 2014-01-04 |    17 |             31
       2 | 2014-01-05 |    18 |             49
       2 | 2014-01-06 |     1 |             50
       2 | 2014-01-07 |     9 |             59
       2 | 2014-01-08 |    18 |             77
       3 | 2014-01-02 |    10 |             10
       3 | 2014-01-03 |     4 |             14
       3 | 2014-01-04 |    14 |             28
       3 | 2014-01-05 |     8 |             36
       3 | 2014-01-06 |    16 |             52
       3 | 2014-01-07 |     7 |             59
       3 | 2014-01-08 |     1 |             60
(21 rows)

Vielen Dank für den Lösungsansatz mit dem besseren Design.
Gibt es denn keine bessere Lösung, ohne das Tabellendesign zu ändern?

Nicht wirklich. Du könntest Dir eine Stored Proc schreiben, die das vereinfacht. Es bleibt aber dann noch immer ein gruseliges Design und es wird von der Performance grottig sein.

Du kannst übrigens den Day of year mit extract aus dem Datum bestimmen. da brauchst du keine Extraspalten anlegen. (Siehe Handbuch :wink:)

Gruß Uwe

Danke für die Antwort, gisman.
Der day-of-year ist nicht das Problem. Der liegt ja in den Originaldaten (in der sub-optimalen Tabellestruktur) bereits vor.
Das Problem bei der Umstrukturierung der Tabellen ist eher das umgekehrte: nämlich year und day-of-year zu year-month-day zu konvertieren. Aber das habe ich bereits über PHP gelöst.
Aber danke dennoch für den Hinweis. Eine datum-Spalte ist ausreichend - wie schon aus der Anleitung von akretschmer hervorgeht.
Zu dem Lösungsansatz von akretschmer: da ich nicht das Aufsummieren nicht nur für jede station sondern auch für jedes Jahr getrennt benötige, heißt die Abfrage nun:
SELECT *, SUM(menge)
OVER (PARTITION BY station, (SELECT EXTRACT(YEAR FROM datum) AS jahr) ORDER BY datum) AS summe_bis_hier
FROM regen;

Nachtrag zu Performance:
ich habe meine 368-spaltige Tabelle (T368) in die vorgeschlagene 3-spaltige Struktur (T3) gebracht.

Unsere Standard-Abfrage (SELECT * FROM tabelle WHERE station=1000) wird für T368 in der Hälfte der Zeit erledigt, die T3 dafür benötigt.
Für die Aufsummier-Abfrage - und darauf bezog sich die Anmerkung von akretschmer richtigerweise - sieht das ganz anders aus:
Dafür benötigt pg mit der T368 15x so lange wie mit der T3.

Allerdings habe ich ein ganz anderes Problem: Speicherplatz.
T368 hat 368 smallint columns und 39000 rows und benötigt laut table statistics 30MB plus 2MB für den Primary key.
T3 hat 2 smallint und 1 date coulumns und 14245000 rows. Laut table statistics sind das 600MB plus 300MB für den Primary Key.

Da ich mit 24 solcher Tabellen hantiere wären das gegenüber den gegenwärtigen 768MB in der T368 Struktur 21600MB in der T3-Struktur.
Und so viel Speicherplatz auf dem online-Server bekommen wir nicht genehmigt. Damit hat sich dieses Problem erledigt.

Wohin können wir ein Angebot schicken?