Daten aus verschiedenen Spalten einer Tabelle abrufen

Hallo zusammen,
ich habe ein ziemlich kompliziertes Problem:
Ich habe die folgende Tabelle (siehe Anhang)
Die Spalten VAL00 bis VAL19 enthalten Kosten über 20 Jahre, wobei VAL00 die Kosten des Startjahres enthalten.
Das heißt für den ersten Datensatz sind Kosten für die Jahre 1999 bis 2018 angegeben, für den nächsten Datensatz
Kosten für die Jahre 2001 bis 2020 usw.
Auslesen möchte ich die Kosten für die Jahre 2005 bis 2009.
Ich muss also dafür aus dem ersten Datensatz die VAL06 bis VAL10 “herauspicken”,
für den zweiten Datensatz die VAL04 bis VAL08 usw.
Ich weiß beim besten Willen nicht, wie ich das machen soll.
Geht das mit “einfachem” SQL?

Ich hoffe, dass ich das genügend erklärt habe.

Kann mir da bitte jemand einen Tipp geben?
Wenn es nötig wird sende ich gerne CREATE und INSERT-Scripts ein.
Vielen lieben Dank
Christine

Du hast ein kapottes Tabellendesign.


Geht das mit “einfachem” SQL?

Ja, aber nicht trivial.

Vereinfachtes Beispiel:

test=# create table jahre (startjahr int, s01 int, s02 int, s03 int);
CREATE TABLE
test=*# insert into jahre values (2000, 0,1,2);
INSERT 0 1
test=*# insert into jahre values (2001, 0,10,20);
INSERT 0 1
test=*# insert into jahre values (2002, 0,100,200);
INSERT 0 1
test=*# insert into jahre values (2003, 0,1000,2000);
INSERT 0 1
test=*# commit;
COMMIT
test=# select sum(case when startjahr=2000 then 0 when startjahr=2001 then s03 when startjahr=2002 then s02 when startjahr=2003 then s01 end) from jahre;

Das berechnet Dir die Summe für das Jahr 2004. Falls Du da mehr Jahre willst, geht auch das:

select sum(case when startjahr=2000 then 0 when startjahr=2001 then s03 when startjahr=2002 then s02 when startjahr=2003 then s01 end) as jahr2004, sum(case when startjahr=2000 then s03 when startjahr=2001 then s02 when startjahr=2002 then s01 when startjahr=2003 then 0 end) as jahr2003 from jahre;

Hilft das erst einmal?

Nicht schön, aber bei dem kapotten Design…


Andreas

Hallo Andreas,
irgendwie verstehe ich das mit dem kaputten Tabellendesign nicht.

Ich werd aber erst mal ausprobieren, was du geschrieben hast und melde ich dann wieder, ob es geklappt hat und mir reicht.
Danke erst mal und bis später
Lieben Gruss

[quote=“Christine”]Hallo Andreas,
irgendwie verstehe ich das mit dem kaputten Tabellendesign nicht.

Das hier:

Die Spalten VAL00 bis VAL19 enthalten Kosten über 20 Jahre, wobei VAL00 die Kosten des Startjahres enthalten.
Das heißt für den ersten Datensatz sind Kosten für die Jahre 1999 bis 2018 angegeben, für den nächsten Datensatz
Kosten für die Jahre 2001 bis 2020 usw.

Das ist einfach nur kapott. Falls Du die Chance hast,das noch zu normalisieren, bevor das Dir komplett um die Ohren fliegt, dann solltest Du das bald machen.

Andreas

Hallo Andreas,
habe mal ein wenig versucht, bekomme aber nur “Müll raus”.

Anbei erst mal das CREATE und INSERT Script. Paste den Text direkt hier ein. Ich vermute mal, dass das anhängen des *.txt-Files (Windows Editor) nicht sauber klappt.

Create:
CREATE TABLE INNBDCOST
(
RNUNID VARCHAR2 (255) NOT NULL,
VALUETYPE VARCHAR2 (255) NOT NULL,
SCT1VALUE NUMBER (38,5),
STARTYEAR NUMBER,
VAL00 NUMBER (38,5),
VAL01 NUMBER (38,5),
VAL02 NUMBER (38,5),
VAL03 NUMBER (38,5),
VAL04 NUMBER (38,5),
VAL05 NUMBER (38,5),
VAL06 NUMBER (38,5),
VAL07 NUMBER (38,5),
VAL08 NUMBER (38,5),
VAL09 NUMBER (38,5),
VAL10 NUMBER (38,5),
VAL11 NUMBER (38,5),
VAL12 NUMBER (38,5),
VAL13 NUMBER (38,5),
VAL14 NUMBER (38,5),
VAL15 NUMBER (38,5),
VAL16 NUMBER (38,5),
VAL17 NUMBER (38,5),
VAL18 NUMBER (38,5),
VAL19 NUMBER (38,5)
);

INSERT:

INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘EXTBAYERCOST’, NULL, 1999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘INNCOST’, NULL, 2001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘INTCOST’, NULL, 2000, 0, 0, 0, 0, 0, 0, 10, 0, 40, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘TOTALCOST’, NULL, 2002, 0, 0, 0, 0, 0, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘DEVCOST’, NULL, 2004, 0, 20, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘EXTBMSCOST’, NULL, 2000, 0, 20, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91E6FBC1257395006959FF’, ‘EXTBMSCOST’, NULL, 2001, 0, 20, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91B6FBC667395006959FF’, ‘EINNCOST’, NULL, 2004, 0, 20, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91B6FBC667395006959FF’, ‘INTCOST’, NULL, 2003, 0, 10, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO INNBDCOST( RNUNID, VALUETYPE, SCT1VALUE, STARTYEAR, VAL00, VAL01, VAL02, VAL03, VAL04, VAL05, VAL06, VAL07, VAL08, VAL09, VAL10, VAL11, VAL12, VAL13, VAL14, VAL15, VAL16, VAL17, VAL18, VAL19) VALUES( ‘AC948A9C4A91B6FBC667395006959FF’, ‘INTCOST’, NULL, 2005, 0, 20, 30, 50, 60, 0, 30, 50, 70, 90, 0, 200, 100, 0, 0, 0, 0, 0, 0, 0);

Habe mal nur 10 Datensätze genommen, das muss erst mal reichen.

Habe dann mit folgenden Statement versucht:
select rnunid,
sum(case when startyear=2005 then VAL00
when startyear=2004 then VAL01
when startyear=2003 then VAL02
when startyear=2002 then VAL03
when startyear=2001 then VAL04
when startyear=2000 then VAL05
when startyear=1999 then VAL06
end) “Cost (2005)”,
sum(case when startyear=2005 then VAL01
when startyear=2004 then VAL02
when startyear=2003 then VAL03
when startyear=2002 then VAL04
when startyear=2001 then VAL05
when startyear=2000 then VAL06
when startyear=1999 then VAL07
end) “Cost (2006)”
from innbdcost
group by rnunid
;
Aber da kriege ich nicht raus, was ich will.

Ich erwarte folgende ausgabe:
RNUNID COST (2005) COST (2006) COST (2007) Cost (2008) Cost (2009)


1 20 30 40 100 100

und das über die gesamte Tabelle.
Mein u.a. Statement wirft mir nur genau 2 Datensätze aus. Das kann doch nciht sein, dass ich für jeden Fall jeweils ein “Case when” schreiben muss.
???
Ratlosigkeit
Danke

Das müffelt wie ORACLE… und ist zumindest kein PostgreSQL.

und das über die gesamte Tabelle.
Mein u.a. Statement wirft mir nur genau 2 Datensätze aus. Das kann doch nciht sein, dass ich für jeden Fall jeweils ein “Case when” schreiben muss.
???
Ratlosigkeit
Danke

Vielleicht fällt jemand anders was besseres ein. Mit fällt nur ein, die Daten zu normalisieren. Grob gesagt, eine Tabelle mit den Spalten für einen primary Key, das Jahr und den Wert. Dann reduziert sich das auf Anfänger-SQL.

Andreas

Was Andreas meint:

Es ist falsch, wenn du für jedes Jahr eine Spalte einführst, weil du für ein neues Jahr eine Änderung deiner Tabelle und deiner Applikation brauchst.
Normalerweise lagert man die Jahre in eine weitere Tabelle aus und referenziert bloss in einer Spalte die Jahreszahl bzw. den Eintrag in der Tabelle mit den Jahren.
In deinem Fall ginge das sogar noch einfacher: du fügst bei deinen Datensätzen eine Spalte “Jahr” ein, in der dann 2005, 2006 oder 2007 oder so drin steht und du hast dann exakt eine(!) Spalte, in der jeweils der gesuchte Wert drin steht.

Wenn du dann Daten abfragst, schaust du nicht mehr in die Spalte für das betreffende Jahr sondern du fragst immer die Spalte mit dem Wert ab und vergleichst zusätzlich, ob die Jahreszahl mit der gesuchten übereinstimmt. Und voila, schon wird deine Applikation und deine Anfrage sehr, sehr einfach :wink:

Hallo ads,
So ganz verstehe ich nicht was gemeint ist.
Ich habe doch eine “Startjahr”-Spalte in der Tabelle, die besagt mit welchem jahr die Valuewerte anfangen. Wenn man mein Beispiel nimmt, dann entspricht für den ersten Datensatz das VAL00 dem Wert für das Jahr 1999.
Das ganze reslutiert aus Formulareingaben aus Projektdaten. Deshalb lässt sich die Tabelel nicht anders darstellen, weil die Projekte aus denen die Werte kommen unterschliedliche “Laufzeiten haben” aber eben immer über maximal zwanzig Jahre laufen.
Also brauche ich eine Möglichkeit die Kosten für den fünf-jahresbereicht 2005-2009 zu bekommen und schon das Jahr 2005 entspricht je Datensatz leider einem anderen VALXX.
Danke

Hallo Andreas,
bin ich ggf. im falschen Forum?
Du sagst “das müffelt nach Oracle…” und “… ist kein PostgreSQL…”
Kannst du mir das erklären?
Danke

Na sicher.

Das hier ist ein Forum, wo es um PostgreSQL geht. Den Datentyp “varchar2” kennt PostgreSQL nicht, ich glaub mich aber erinnern zu können, daß das eine Erweiterung von Oracle ist. Auch NUMBER ist in PostgreSQL unbekannt.

Du hattest in dem von Dir gezeigten SQL allerdings exakt diese Typen verwendet.

Kannst Du nun verstehen, was ich meine? Noch mal als Hinweis: das hier ist das pg-forum, und pg steht für PostgreSQL. Steht auch oben im Logo.


Andreas

Davon abgesehen: natürlich kannst Du auch hier fragen, aber so wie wir Deine Beispiel nicht nachvollziehen können, wenn diese Oracle-spezifische Dinge beinhalten, wirst Du möglicherweise Antworten nicht verstehen oder nutzen können, weil die Leute hier nun mal PostgreSQL am Start haben und dessen speziellen Features vielleicht auch nutzen.

Und ja: ob Oracle oder PostgreSQL, egal, Dein Tabellendesign ist so oder so kapott.

Andreas

Deine Tabelle dürfte nicht so aussehen:

VAL00
VAL01
VAL02

VAL19

sondern müsste folgendes Format haben:

VALUE
YEAR

Wenn du einen Wert speicherst, wandert der immer in VALUE und zusätzlich schreibst du das jahr in YEAR.

Danach kannst du dann mit:

WHERE YEAR=2006 deine Werte heraussuchen und das Ergebnis steht immer in VALUE, nicht in VAL01 oder VAL02 oder VAL03 oder … VAL19.

Soweit verständlich?

Noch einmal:

Du machst eine Tabelle mit den Spalten Projekt-Nr, Jahr, Value. Projekt 1 geht 4 Jahre, von 2000 bis 2003, dann noch Projekt 2 und 3. In Deiner Tabelle steht dann:

test=# select * from projekte ;
 id | jahr | val
----+------+-----
  1 | 2000 |  10
  1 | 2001 |  11
  1 | 2002 |  12
  1 | 2003 |  13
  2 | 2002 |  20
  2 | 2003 |  30
  2 | 2004 |  40
  3 | 2005 |  50
(8 rows)

Willst Du nun den Zeitraum von 2001 bis 2005 betrachten, geht das simpel so:

test=*# select id, sum(val) from projekte where jahr between 2001 and 2005 group by id;
 id | sum
----+-----
  3 |  50
  2 |  90
  1 |  36

Mit diesem Schema der Tabelle hast Du folgende Vorteile im Vergleich zu Deinem:

  • es ist egal, wie lange ein Projekt läuft. Du hast dadurch weder Felder mit NULL noch ein Poblem, wenn mal ein Projekt länger als vorgesehen (Spaltenanzahl) läuft.
  • die Anfrage ist sehr simpel
  • du kannst Indexe für den Zeitraum nutzen

Nun verstanden?

Andreas