Join gegen Daten aus dem SQL!?

In einer Tabelle befinden sich Daten zu Kontobewegungen. Ich möchte nun die Summe der Kontobewegungen pro Monat über einen JOIN ermitteln. Aktuell sieht das SQL Statement wie folgt aus:

SELECT Monate.monat, SUM(T.Betrag) AS Summe
FROM Monate M LEFT OUTER JOIN Transaktionen T ON M.monat = T.monat
GROUP BY Monate.monat

Dazu existieren die beiden Tabellen „Monate“ und „Transaktionen“. Die Tabelle Monate ist nur Mittel zum Zweck und besteht aus einer Spalte mit den Werten 1 bis 12.

Frage: Ist es mit SQL Mitteln nicht möglich, auf die Tabelle Monate zu verzichten? Denkbar wäre doch, die Monate per (1,2,…12) zu definieren. Allerdings fehlt hier der Spaltenname. Gibt es eine Möglichkeit, den JOIN über eine Menge, wie sie beispielsweise bei IN (1,2,3,4) definiert wird, auszuführen?

Gruß Markus

Welche Datenbank? Oracle?

Welche Datenbank? Oracle?

Mich interessiert, ob und wie SQL das im Allgemeinen unterstützt. Falls du eine Lösung hast, die nur mit Oracle, DB2 oder Access funktioniert, so interessiert mich auch dieses sehr.

Vielen Dank, Markus

Oracle
In Oracle könnte man es so machen:

select
m.monat,
SUM(T.Betrag)
from
Transaktionen T,
( Select 1 monat from dual
union all
Select 2 monat from dual
union all
Select 3 monat from dual
union all
Select 4 monat from dual
… – hier bis 12 Monate weitermachen
) m
where
m.monat = T.monat
GROUP BY m.monat

Aber ob das von der Performance besser ist, als mit der Hilftabelle wäre zu prüfen…

CU
Nic

Moin Markus,

ähem, irgendwie verstehe ich das Problem nicht. Wenn in deiner Transaktionstabelle die Monate stehen warum brauchst du dann noch die Monatstabelle??

select monat, sum(betrag)
from Transaktion
where monat in (1,2,3,4,5,6,7,8,9,10,11,12)
group by monat

Oder hab ich die Tabellenstruktur von Transaktion mißverstanden ??

Viele Grüße

der (diesmal wirklich) Ratlose

Moin Markus,

ähem, irgendwie verstehe ich das Problem nicht. Wenn in deiner
Transaktionstabelle die Monate stehen warum brauchst du dann
noch die Monatstabelle??

select monat, sum(betrag)
from Transaktion
where monat in (1,2,3,4,5,6,7,8,9,10,11,12)
group by monat

Oder hab ich die Tabellenstruktur von Transaktion
mißverstanden ??

Nein, du hast es schon richtig verstanden. Dein SQL-Statement liefert aber nur dann eine Zusammenfassung für jeden Monat, wenn in jedem Monat auch wirklich eine Transaktion stattgefunden hat. Ist die Transaktionstabelle leer, so liefert dir dein SQL ebenfalls eine leere Menge. Bei einer leeren Tabelle möchte ich trotzdem eine Summe für jeden Monat haben, hier ist sie dann eben 0.

Markus

In Oracle könnte man es so machen:

select
m.monat,
SUM(T.Betrag)
from
Transaktionen T,
( Select 1 monat from dual
union all
Select 2 monat from dual
union all
Select 3 monat from dual
union all
Select 4 monat from dual
… – hier bis 12 Monate weitermachen
) m
where
m.monat = T.monat
GROUP BY m.monat

Genau das habe ich gesucht! Weisst du, ob das auch mit MS Access möglich ist?
„FROM dual“ ist ja oracle-spezifisch…

Aber ob das von der Performance besser ist, als mit der
Hilftabelle wäre zu prüfen…

Aufgrund der Länge des Statements bin ich mir nun auch nicht mehr sicher. Problematisch fand ich die Monatstabelle, da durch Maniplulationen hier andere Ergebnisse verfälscht würden. Ausserdem ist eine Liste mit 12 Elementen vom Typ Zahl nicht wirklich anspruchsvoll.

Markus

wie wär´s dann damit ?

select monat, sum(nvl(betrag,0))
from Transaktion
where monat in (1,2,3,4,5,6,7,8,9,10,11,12)
group by monat

hi!

mußt du ja gar nicht

select ‚01‘,sum(t.betrag)
from transaktionen t
where t.monat = ‚01‘
union
select ‚02‘,sum(t.betrag)
from transaktionen t
where t.monat = ‚02‘

bzw. unter access glaub ich doppelte hochkomma …

grüße,
tomh

ps: hab’s jetzt nicht unbedingt ausprobiert …
pps: allerdings ist diese lösung alles andere als elegant …

Gleiches Problem, wenn Transaktion leer ist, dann ist auch das Ergebis dieser Abfrage leer. Man muss sich klar machen, dass die WHERE-Clause Filtert. Und durch einen Filter lassen sich keine fehlenden Daten ergänzen.
Du kannst es ja mal selbst ausprobieren!

Trotzdem Danke,

Markus

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

hi!

mußt du ja gar nicht

select ‚01‘,sum(t.betrag)
from transaktionen t
where t.monat = ‚01‘
union
select ‚02‘,sum(t.betrag)
from transaktionen t
where t.monat = ‚02‘

bzw. unter access glaub ich doppelte hochkomma …

Sieht zwar ähnlich aus, kann aber nicht funktionieren, du filterst hier lediglich Zeilen aus, wenn Transaktionen leer ist, bleibt auch das Ergebnis leer.
Damit das nach meinen Vorstellungen funktionieren kann, ist ein Kreuzprodukt auf zwei Tupeln notwendig, bei zwei Tabellen ist das der Fall. Ziel ist es eine zweite Datenmenge zu schaffen, um diese in Relation mit den Transaktionen bringen zu können.

Trotzdem Danke,

Markus

hi!

Sieht zwar ähnlich aus, kann aber nicht funktionieren, du
filterst hier lediglich Zeilen aus, wenn Transaktionen leer
ist, bleibt auch das Ergebnis leer.

irrtum: ich „filtere“ zwar die tabelle, jedoch sind die monate („1“,„2“, etc.) hardcodierte werte, die auf jeden fall eine zeile als ergebnis liefern, da aus der transaktionstabelle nur die summe (= aggregatsfunktion (?)) berechnet und kein enzelner wert herausgeholt wird

grüße,
tomh

ps: ich hab’s jetzt sogar ausprobiert (sql+ unter oracle)

SQL\> select \* from transaktion;

 MONAT ZAHL
---------- ----------
 1 2
 3 1
 5 10

SQL\> get afiedt.buf
 1 select 1,nvl(sum(zahl),0)
 2 from transaktion
 3 where monat = 1
 4 union
 5 select 2,nvl(sum(zahl),0)
 6 from transaktion
 7 where monat = 2
 8 union
 9 select 3,nvl(sum(zahl),0)
 10 from transaktion
 11 where monat = 3
 12 union
 13 select 4,nvl(sum(zahl),0)
 14 from transaktion
 15 where monat = 4
 16 union
 17 select 5,nvl(sum(zahl),0)
 18 from transaktion
 19 where monat = 5
 20 union
 21 select 6,nvl(sum(zahl),0)
 22 from transaktion
 23 where monat = 6
 24 union
 25 select 7,nvl(sum(zahl),0)
 26 from transaktion
 27 where monat = 7
 28 union
 29 select 8,nvl(sum(zahl),0)
 30 from transaktion
 31 where monat = 8
 32 union
 33 select 9,nvl(sum(zahl),0)
 34 from transaktion
 35 where monat = 9
 36 union
 37 select 10,nvl(sum(zahl),0)
 38 from transaktion
 39 where monat = 10
 40 union
 41 select 11,nvl(sum(zahl),0)
 42 from transaktion
 43 where monat = 11
 44 union
 45 select 12,nvl(sum(zahl),0)
 46 from transaktion
 47\* where monat = 12
SQL\> /

 1 NVL(SUM(ZAHL),0)
---------- ---------------- 
 1 2
 2 0
 3 1
 4 0
 5 10
 6 0
 7 0
 8 0
 9 0
 10 0
 11 0
 12 0

12 Zeilen ausgewählt.

SQL\>

Sieht zwar ähnlich aus, kann aber nicht funktionieren, du
filterst hier lediglich Zeilen aus, wenn Transaktionen leer
ist, bleibt auch das Ergebnis leer.

irrtum: ich „filtere“ zwar die tabelle, jedoch sind die monate
(„1“,„2“, etc.) hardcodierte werte, die auf jeden fall eine
zeile als ergebnis liefern, da aus der transaktionstabelle nur
die summe (= aggregatsfunktion (?)) berechnet und kein
enzelner wert herausgeholt wird

Du hast recht! Ich hatte nicht bedacht, dass eine Aggregation immer eine
Ergebniszeile liefert! Möglicherweise bringt mich dieser Ansatz etwas weiter.

Vielen Dank für diese ausführliche Erklärung!

Gruß Markus