Anmelden

View Full Version : SQL Problem / Frage



Bratmaxxe
04-02-09, 06:11
Hallo SQL'er,

habe ein Problem. Gegeben ist nachfolgende Tabellenstruktur:


http://www.bild-upload.net/bild.php/7871,tables4CHBG.jpg


Tabelle 1 (MYC4REP):

C4RCTX, C4D0NB, C4LFDN sind Primärschlüssel

Tabelle 2 (MYC5REP):

C5RCTX, C5D0NB, C5LFDN, C5CRNB, C5W3NB, C5W4NB, C5XXTX sind Primärschlüssel

Tabelle 3 (MWI5REP):

I5RCTX, I5D0NB, I5CRNB, I5W3NB, I5W4NB, I5XXTX sind Primärschlüssel


Tabelle 1 stellt einen Kopfsatz dar.
Tabelle 2 ist die dazugehörige Positionstabelle (Verknüpfung aus Tabelle 1 und 3).
Tabelle 3 (eigentliche Datentabelle)

In einer Java Anwendung möchte ich nun folgende Informationen darstellen:

Aus Tabelle 1:
C4LFDN und die Bezeichnung (Spalte hinter C4LFDN)

Aus Tabelle 2:
Min und Max C5W4NB
Anzahl der Datensätze aus Tabelle 2 die zu einer Kopfposition C4LFDN gehören

Aus Tabelle 3:
Anzahl der Datensätze die als Attribut ein 'J' aufweisen (Spalte I5NFO1 nicht im Screenshot enthalten).


Beispiel mit C4LFDN = 1
Darzustellende Informattion:
1(c4lfdn aus Tabelle 1) ma (text aus Tabelle 1) 1220(min C5W4NB aus Tabelle 2) 1380(max C5W4NB aus Tabelle 2) 4(Anzahl Datensätze aus Tabelle2) 2(Anzahl derer, die in Tabelle 3 ein 'J' aufweisen)


Soweit bin ich schon gekommen:

SELECT MYC4REP.*,
(SELECT MIN(C5W4NB) FROM MYC5REP WHERE C4RCTX = C5RCTX AND C4D0NB = C5D0NB AND C4LFDN = C5LFDN) AS MIN_C5W4NB,
(SELECT MAX(C5W4NB) FROM MYC5REP WHERE C4RCTX = C5RCTX AND C4D0NB = C5D0NB AND C4LFDN = C5LFDN) AS MAX_C5W4NB,
(SELECT COUNT(*) FROM MYC5REP WHERE C4RCTX = C5RCTX AND C4D0NB = C5D0NB AND C4LFDN = C5LFDN) AS ANZ_IN_TABELLE_2
FROM MYC4REP
WHERE MYC4REP.C4RCTX = '100' AND MYC4REP.C4D0NB = 676 ORDER BY C4RCTX

mir fehlt nur noch die Anzahl der Datensätze aus Tabelle 3, wo bei I5NFO1 ein 'J' vorhanden ist...

Wie bekomme ich die da mit rein ?

Würde mich über eine Hilfe freuen,

VlG
Bratmaxxe

B.Hauser
04-02-09, 08:06
Hallo,

zuerst einmal, wenn man mit Sub-Selects arbeitet, sollten man Sub-Selects in der Select-Anweisung wenn möglich vermeiden und lieber in der From-Anweisung einsetzen.

In Deinem Fall wird die gleiche Abfrage 3x ausgeführt, um den Minimal-Wert, den Maximal-Wert und die Anzahl zu bestimmen. Besser wäre natürlich die Tabelle nur einmalig zu lesen und dabei den Minimal- und Maximal-Wert, sowie die Anzahl ermitteln.

Weiterhin, muss Du in solchen Fällen die Gesamt-Abfrage zumindest geistig in Einzel-Abfragen zerlegen und anschließend wieder zu einem Großen Ganzen zusammen fassen.

Soweit ich das überblickt habe werden die folgenden Abfrage benötigt:

Tabelle MYC4REP, aus der nur die Sätze mit C4RCTX = '100' und C4D0NB = 676 selectiert werden.
Die Tabelle MYC5REP muss für alle Sätze mit C4RCTX = '100' und C5D0NB = 676 (beides Schlüssel-Felder) auf C5rctx, c5d0nb, c5lfdn verdichtet werden. Auf dieser Ebene wird dann der Minimal-Wert und Maximal-Wert, sowie die Anzahl ermittelt.
Das Ergebnis aus Abfrage 1 muss mit Tabelle MYC5REP über C5RCTX, C5D0NB, C5LFDN verknüpft werden, da nur MYC5REP über alle Schlüssel-Felder mit Tabelle 3 verknüpft werden kann. Die Verknüpfung der 3 Abfragen muss dann wieder auf RCTX, D0NB und LFDN verdichtet werden und nur die Sätze mit J in INF01 gezählt werden.
Die einzelnen Teilergebnisse werden dann miteinander über RCTX, D0NB und LFDN verknüpft und die gewünschten Spalten ausgewählt und wie gewünscht sortiert.


Die Abfrage könnte im Endeffekt etwa so aussehen:

With a as (Select *
from MyC4Rep
Where C4RCTX = '100' AND C4D0NB = 676)
b as (Select C5rctx, c5d0nb, c5lfdn,
Min(C5W4NB) as Min_cw5nb,
Max(C5w4nb) as Max_CW5NB,
Count(*) as Anz_In_Tabelle2
from MYC5Rep
Where C5RCTX = '100' and C5D0NB = 676)
Group by c5rctx, c5d0nb, c5fldn),
c as (Select I5RCTX, I5D0NB, C5LFDN as I5LFDN,
count(I5NF01) Anz3
from a join MyC5REP on C4RCTX = C5RCTX
and C4D0NB = C5D0NB
and C4LFDN = C5LFDN
join Tab3 on C5RCTX = I5RCTX
and C5D0NB = I5RCTX
and C5CRNB = I5CRNB
and C5W3NB = I5W3NB
and C5W4NB = I5W4NB
and C5XXTX = I5XXTX
Where I5NF01 = 'J')
SELECT a.*, Min_Cw5nb, Max_Cw5NB, Anz_in_Tabelle2, Anz3
FROM a join b on c4rctx = c5rctx and c4d0nb = c5d0nb and c4lfdn = c5lfdn
join c on C4rctx = i5rctx and c4d0nb = i5d0nb and c4lfdn = i5lfdn

Birgitta

Pikachu
04-02-09, 09:55
Also mir ist noch nicht klar, welche Datensätze aus Datei 3 zum Beispiel zu 100/676/1/1220(min)/1380(max)/4(count) gehören.

Bratmaxxe
04-02-09, 10:24
Also mir ist noch nicht klar, welche Datensätze aus Datei 3 zum Beispiel zu 100/676/1/1220(min)/1380(max)/4(count) gehören.

Hi Pikachu,

dass sind die Daten aus Tabelle 2...

Tabelle 2 zu 3 ist eine 1:1 Verknüpfung
Tabelle 1 zu 2 ist eine 1:n Verknüpfung

Gruß
Bratmaxxe

Pikachu
04-02-09, 10:44
Vielleicht so:

SELECT C4RCTX,C4D0NB,C4LFDN,C4TEXT,
B.C5CRNB,B.C5W3NB,B.C5W4NB,B.C5XXTX,
C5W4NBMIN,C5W4NBMAX,C5COUNT,I5COUNT
FROM MYC4REP AS A,
MYC5REP AS B,
(SELECT C5RCTX,C5D0NB,C5LFDN,
MIN(C5W4NB) AS C5W4NBMIN,
MAX(C5W4NB) AS C5W4NBMAX,
COUNT(*) AS C5COUNT
FROM MYC5REP
GROUP BY C5RCTX,C5D0NB,C5LFDN) AS S
LEFT OUTER JOIN
(SELECT I5RCTX,I5D0NB,I5CRNB,I5W3NB,I5W4NB,I5XXTX,
COUNT(*) AS I5COUNT
FROM MYI5REP
WHERE I5NFO1='J'
GROUP BY I5RCTX,I5D0NB,I5CRNB,I5W3NB,I5W4NB,I5XXTX) AS I
ON I5RCTX=B.C5RCTX AND I5D0NB=B.C5D0NB AND
I5CRNB=B.C5CRNB AND I5W3NB=B.C5W3NB AND
I5W4NB=B.C5W4NB AND I5XXTX=B.C5XXTX
WHERE C4RCTX=B.C5RCTX AND C4D0NB=B.C5D0NB AND C4LFDN=B.C5LFDN AND
C4RCTX=S.C5RCTX AND C4D0NB=S.C5D0NB AND C4LFDN=S.C5LFDN

Bratmaxxe
04-02-09, 12:29
Hi,

danke für die Hilfe !

Die Abfrage von Birgitta habe ich noch etwas angepasst:



With a as (Select *
from MyC4Rep
Where C4RCTX = '100' AND C4D0NB = 676),

b as (Select C5rctx, c5d0nb, c5lfdn,
Min(C5W4NB) as Min_cw5nb,
Max(C5w4nb) as Max_CW5NB,
Count(*) as Anz_In_Tabelle2
from MYC5Rep
Where C5RCTX = '100' and C5D0NB = 676
group by c5RCTX, c5D0NB, c5LFDN),

c as (Select I5RCTX, I5D0NB, C5LFDN AS I5LFDN,
count(*) as Anz3
from a join MyC5REP on C4RCTX = C5RCTX
and C4D0NB = C5D0NB
and C4LFDN = C5LFDN
join mwi5rep on C5RCTX = I5RCTX
and C5D0NB = I5D0NB
and C5CRNB = I5CRNB
and C5W3NB = I5W3NB
and C5W4NB = I5W4NB
and C5XXTX = I5XXTX
Where I5NFo1 = 'J'
group by I5RCTX, I5D0NB, C5LFDN )
SELECT a.*, Min_Cw5nb, Max_Cw5NB, Anz_in_Tabelle2, anz3
FROM a join b on c4rctx = c5rctx and c4d0nb = c5d0nb
and c4lfdn = c5lfdn
join c on C4rctx = i5rctx and c4d0nb = i5d0nb and c4lfdn = i5lfdn

Funktioniert tadellos auf der AS400...

Allerdings nicht für eine mobile Datenbank (H2Databse) - scheinbar wird dieser Syntax nicht unterstützt...

SQL Grammar (http://www.h2database.com/html/grammar.html)

Wie kann man das dann trotzdem so hinbiegen, dass die H2 den Ausdruck versteht ?

Gruß
Bratmaxxe

Fuerchau
04-02-09, 13:11
Wenn CTE's und "from (select ...)" nicht unterstützt werden, hilft nur eine Zerlegeung des SQL's oder ggf. eine View-Erstellung mit der dann gejoint wird.