join über mehrere Tabellen mit auswahlkriterien oder begrenzung

Hallo liebes Forum,

ich habe mal wieder ein SQL-Problem.

Ich habe eine Tabelle in der ich Stücklisten zusammenstelle.
Zu jedem Eintrag in einer Stückliste gibt es einen Stammdatensatz.
Also eine einfache n:m Beziehung.

Zu jedem Stammdatensatz gibt es zwei Tabellen in denen Preisinformationen stehen KÖNNEN. Jeweils mit einem Datum und einer Einheit (Preis pro Stück, pro 100 Stück).

stammdaten
laufendenummer | name

stueckliste
laufendenummer_stammdaten | laufendenummer_stueckliste

preis1
laufendenummer_stammdaten | datum | preis | einheit

preis2
laufendenummer_stammdaten | datum | preis | einheit



Jetzt möchte ich mir die Srücklisten ausgeben lassen und für jeden Eintrag auch gleich den aktuellesten Preis mit Einheit.
Als Resultat sollte also sowas rauskommen, jeweils für jede Position eine Ergebniszeile die so aussieht:

laufendenummer_stammdaten | preis | einheit | datum
laufendenummer_stammdaten | preis | einheit | datum
laufendenummer_stammdaten | preis | einheit | datum

Der Preis kommt aus einer der beiden Tabellen, preis1 oder preis2, aus welcher bestimmt sich über das Datum.

Wie kann ich das lösen.
Ich finde keinen Ansatz.
group by hilft mir nicht, oder?


Ein weiterer Ansatz wäre, dass ich erstmal die beiden jeweils aktuellesten Preise aus den Tabellen entnehme und dann über das Programm, dass dahinter steht auswerten lasse welcher Preis stimmt.
Dann bleibt aber noch die Frage, wie ich das Ergebnis eines Left Join über die Preistabellen auf eine Ergebniszeile pro Stammdatensatz begrenzen kann,wobei dann wieder das Datum ausschlaggebend ist.

laufendenummer_stammdaten | preis1 | einheit1 | datum1 | preis2 | einheit2 | datum2
laufendenummer_stammdaten | preis1 | einheit1 | datum1 | preis2 | einheit2 | datum2
laufendenummer_stammdaten | preis1 | einheit1 | datum1 | preis2 | einheit2 | datum2




Ich hoffe ihr habt eine Idee!

Danke für eure Hilfe!
Crypi

Könntest Du statt dem Roman vielleicht auch Copy&Paste-fähige SQL-Befehle zum Erstellen der Tabellen bringen?


Jetzt möchte ich mir die Srücklisten ausgeben lassen und für jeden Eintrag auch gleich den aktuellesten Preis mit Einheit.
Als Resultat sollte also sowas rauskommen, jeweils für jede Position eine Ergebniszeile die so aussieht:

laufendenummer_stammdaten | preis | einheit | datum
laufendenummer_stammdaten | preis | einheit | datum
laufendenummer_stammdaten | preis | einheit | datum

Der Preis kommt aus einer der beiden Tabellen, preis1 oder preis2, aus welcher bestimmt sich über das Datum.

Wie bestimmt sich das, nach welcher Regel? Dies ist nicht klar.


Wie kann ich das lösen.
Ich finde keinen Ansatz.
group by hilft mir nicht, oder?

Nein, erst einmal mußt Du alle Deine Tabellen JOINen. Nach welcher Regel wird der Preis gezogen?


Ich hoffe ihr habt eine Idee!


test=*# select * from stammdaten ;
 laufendenummer |   name
----------------+-----------
              1 | stammdat1
              2 | stammdat2
              3 | stammdat3
(3 rows)

test=*# select * from stueckliste ;
 laufendenummer_stammdaten | laufendenummer_stueckliste
---------------------------+----------------------------
                         1 |                          1
                         2 |                          1
                         3 |                          1
(3 rows)

test=*# select * from preis1;
 laufendenummer_stammdaten |   datum    | preis | einheit
---------------------------+------------+-------+---------
                         1 | 2010-08-18 |   100 | Kilo
(1 row)

test=*# select * from preis2;
 laufendenummer_stammdaten |   datum    | preis | einheit
---------------------------+------------+-------+---------
                         3 | 2010-08-18 |   300 | Kilo
(1 row)

test=*# select sl.laufendenummer_stammdaten, coalesce(p1.preis,0) + coalesce(p2.preis,0) as preis, coalesce(p1.einheit,'') || coalesce(p2.einheit,'') as einheit from stueckliste sl left join preis1 as p1 on (sl.laufendenummer_stammdaten=p1.laufendenummer_stammdaten) left join preis2 p2 on (sl.laufendenummer_stammdaten=p2.laufendenummer_stammdaten);
 laufendenummer_stammdaten | preis | einheit
---------------------------+-------+---------
                         1 |   100 | Kilo
                         2 |     0 |
                         3 |   300 | Kilo
(3 rows)

Mal so als Anfang.


Andreas, der grad das Firefox-Plugin ‘All-Text’ testet …

vielen Dank für die schnelle Antwort!

welcher Preis genommen wird, entscheidet sich darüber welches Datum aktueller ist.
Wenn in preis1 ein Preis vom 18.08.2010 steht und in preis2 ein Preis vom 17.08.2010, dann soll der Preis aus preis1 genommen werden.

Entschuldige bitte, ich werde zukünftig entsprechende copy&paste Beispiele erstellen!

Ich habe dein Beispiel ausprobiert.
Sobald bei mir in beiden Tabellen für den gleichen Stamdatensatz ein Preis steht, dann werden die werte addiert.


An was ich eher dachte, war:

Select p1.preis, p1.einheit, p2.preis, p2.einheit, sl.laufendenummer_stammdaten from stueckliste as sl
left join preis1 as p1
on p1.laufendenummer_stammdaten = sl.laufendenummer_stammdaten
left join preis2 as p2
on p2.laufendenummer_stammdaten = sl.laufendenummer_stammdaten
order by p1.datum, p2.datum

wobei jeweils nur der aktuellste Datensatz aus p1 und p2 genommen wird, so dass man garantiert pro Stücklisteneintrag nur eine Ergebniszeile erhält.
Und wie man das einschränken kann, dass weiß ich nicht.

Oder als Alternative, wo mir aber gänzlich der Ansatz fehlt, es wird bevor die Ergebniszeile gebildet wird verglichen welcher Datensatz, p1 oder p2, der aktuellste ist.

Ich hoffe ich kann verständlich machen was ich meine!

Crypi

Hast du die Möglichkeit, diese Datenbank noch umzudesignen?
Das hört sich alles recht krank an.



test=*# select * from stueckliste ;
 laufendenummer_stammdaten | laufendenummer_stueckliste
---------------------------+----------------------------
                         1 |                          1
                         2 |                          1
                         3 |                          1
(3 rows)

test=*# select * from preis1;
 laufendenummer_stammdaten |   datum    | preis | einheit
---------------------------+------------+-------+---------
                         1 | 2010-08-18 |   100 | Kilo
                         2 | 2010-08-16 |    10 | Kilo
(2 rows)

test=*# select * from preis2;
 laufendenummer_stammdaten |   datum    | preis | einheit
---------------------------+------------+-------+---------
                         3 | 2010-08-17 |   300 | Kilo
                         2 | 2010-08-19 |  1000 | Kilo
(2 rows)

test=*# select sl.laufendenummer_stammdaten, case when p1.datum > p2.datum then coalesce(p1.preis,0) else coalesce(p2.preis,0) end as preis, case when p1.datum > p2.datum then p1.einheit else p2.einheit end as einheit from stueckliste sl left join preis1 as p1 on (sl.laufendenummer_stammdaten=p1.laufendenummer_stammdaten) left join preis2 p2 on (sl.laufendenummer_stammdaten=p2.laufendenummer_stammdaten);
 laufendenummer_stammdaten | preis | einheit
---------------------------+-------+---------
                         1 |     0 |
                         2 |  1000 | Kilo
                         3 |   300 | Kilo
(3 rows)

besser?


Andreas

Okay, man sollte noch prüfen, ob es überhaupt Einträge in beiden Tabellen gibt. Muß man halt a bissl mit CASE basteln, das Prinzip sollte aber erkennbar sein, oder?

Andreas