Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Abfrage in Firebird DB über 6 Tabellen (https://www.delphipraxis.net/193791-abfrage-firebird-db-ueber-6-tabellen.html)

daniel775 9. Sep 2017 12:22

Datenbank: Firebird • Version: 2.5.2.26540 • Zugriff über: SQL-Manager lite

Abfrage in Firebird DB über 6 Tabellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,


ich verzweifel gerade an einer Abfrage bzw. an dem Konstrukt der Tabellen in Firebird.

Also die Tabellen müssen folgende Anforderungen erfüllen:
- Ein Artikel muss mehreren Lieferanten zuzuordnen sein.
- Jeder Artikel kann eine fremde Artikel-Nr eines Lieferanten haben.
- Jeder Artikel hat unterschiedliche Einkaufspreise von jeden Lieferanten mit unterschiedlichen Zeiträumen.


Auszug aus dem Aufbau der Tabellen:
(Siehe Anhang)


SQL-Query
Code:

SELECT k.Firmenname, k.KREDITORNR, k1.Datum, pr.LISTENPREIS_NETTO, pr.EKPREIS_NETTO
FROM
KREDITOREN as k,
KREDITOR_PREISE as pr,
REL_KREDITOR_ARTIKEL as r,
REL_KRED_ART_PREISE as rp
JOIN KREDITOREN on k.ID = r.KREDITOR_ID
JOIN REL_KREDITOR_ARTIKEL on r.id = rp.KREDITOR_ART_ID
JOIN REL_KRED_ART_PREISE on rp.KREDITOR_PREISE_ID = pr.id
JOIN (SELECT k.id, MAX(pr.SDATETIME) as Datum
FROM
KREDITOREN as k,
REL_KREDITOR_ARTIKEL as r,
KREDITOR_PREISE as pr
JOIN KREDITOREN on k.ID = r.KREDITOR_ID
JOIN REL_KREDITOR_ARTIKEL on r.KREDITOR_ART_ID = pr.KREDITOR_ART_ID
GROUP BY k.id
) k1
on k1.id = k.id
GROUP BY k.Firmenname, k.KREDITORNR, k1.Datum, pr.LISTENPREIS_NETTO, pr.EKPREIS_NETTO
ORDER BY k1.Datum;

Ergebnis meiner Abfrage ist, das ich 4 Zeilen Ergebnis bekomme, obwohl ich nur 2 Erwarte mit
jeweils eine Zeile und den aktuellen Preisen der beiden Lieferanten.

Wobei das Datum von dem Datensatz der eigentlich nicht im Ergebnis sein soll, das Datum vom Datensatz übernommen hat, das durch "JOIN (SELECT k.id, MAX(pr.SDATETIME) as Datum" als größten Datensatz selektiert wurde.

Die Tabelle "Kreditor_Preise" hat 4 Zeilen. Jeder Lieferant der beiden hat zwei Zeilen. Wobei jede Zeile ein unterschiedliches Datum hat. Also das Ergebnis soll sein 2 Zeilen, 2 Lieferanten, 2 aktuelle Preise. Also mit dem ältesten Datum.

Also zurück zu meinen eigentlichen Frage. Wie erreiche ich bei einer gruppierten Abfrage das nur der Datensatz mit dem ältesten Datum in der Ergebnismenge ist?
Wie muss ich die Tabellen umdesignen um die o.g. anfoderungen zu erfüllen?


Beispiel:
ID Datum Listenpreis Einkaufspreis
1 05.05.2017 699,00 492,70
2 13.08.2017 599,00 392,70
3 25.05.2017 749,00 654,99
4 05.09.2017 799,00 699,99


Über einen Lösungsansatz über den ich auch nachgedacht habe wäre folgender:

D Datum Listenpreis Einkaufspreis Aktiv
1 05.05.2017 699,00 492,70 0
2 13.08.2017 599,00 392,70 1
3 25.05.2017 749,00 654,99 0
4 05.09.2017 799,00 699,99 1

Halt mit einen zusätzlichen Datenfeld "Aktiv" :coder2:


Danke für das Lesen, hoffe auf zahlreiche-/hilfreiche Antworten :lol:

Neumann 10. Sep 2017 09:02

AW: Abfrage in Firebird DB über 6 Tabellen
 
Das ganze sieht für mich - der weder alle Tabellenstrukturen kennt noch genügend Beispieldaten hat - erstmal etwas undurchsichtig aus.

Man könnte es mit 2 Ansätzen (auch kombinierbar) vereinfachen:

1. Mit Views arbeiten, die vereinfachte Zwischentabellen für die Abfrage liefern.

2. Mit einer Stored Procedure arbeiten.

Habe auch schon das Problem gehabt, dass zu viele Joins in einer Abfrage oft ein Ergebnis liefern, das man nicht erwartet oder haben will.

hoika 10. Sep 2017 09:25

AW: Abfrage in Firebird DB über 6 Tabellen
 
Hallo,
bei LaTex heißt es in solchen Fällen immer "Minimal-Beispiel",
also poste eine GDB an, die eine minimale Anzahl an Datensätzen enthält,
aber bei deiner Query falsche Ergebnisse liefert.

Dann noch mal:
Ist
Soll

daniel775 10. Sep 2017 11:50

AW: Abfrage in Firebird DB über 6 Tabellen
 
Liste der Anhänge anzeigen (Anzahl: 2)
OK,

ich habe einen Auszug aus den Tabellen gebaut. Die DB befindet sich im Anhang. Das SQL Script zum extrahieren wollte leider nicht richtig funktionieren. Hänge es aber trotzdem mal an.


SQL Statement für die Abfrage:

SELECT k.Firmenname, k.KREDITORNR, k1.Datum, pr.LISTENPREIS_NETTO, pr.EKPREIS_NETTO
FROM
KREDITOREN as k,
KREDITOR_PREISE as pr,
REL_KREDITOR_ARTIKEL as r,
REL_KRED_ART_PREISE as rp
JOIN KREDITOREN on k.ID = r.KREDITOR_ID
JOIN REL_KREDITOR_ARTIKEL on r.id = rp.KREDITOR_ART_ID
JOIN Kreditor_Preise on rp.KREDITOR_PREISE_ID = pr.id
JOIN (SELECT k.id, MAX(pr.SDATETIME) as Datum
FROM
KREDITOREN as k,
REL_KREDITOR_ARTIKEL as r,
KREDITOR_PREISE as pr
JOIN KREDITOREN on k.ID = r.KREDITOR_ID
JOIN REL_KREDITOR_ARTIKEL on r.KREDITOR_ART_ID = pr.KREDITOR_ART_ID
GROUP BY k.id
) k1
on k1.id = k.id
GROUP BY k.Firmenname, k.KREDITORNR, k1.Datum, pr.LISTENPREIS_NETTO, pr.EKPREIS_NETTO
ORDER BY k1.Datum;

Komischerweise bekomme ich bekomme ich jetzt nur einen Lieferanten bei der Abfrage.

hstreicher 10. Sep 2017 12:21

AW: Abfrage in Firebird DB über 6 Tabellen
 
Ich würde erst mal die Doppelten Tabellen rauswerfen und dann entweder SQL 89 oder SQL 92 Syntax verwenden und nicht beides gleichzeitig

mfg Hannes

p80286 10. Sep 2017 14:27

AW: Abfrage in Firebird DB über 6 Tabellen
 
versuch es mal hiermit:
SQL-Code:
SELECT K.irgendwas,KP.Sdatetime
FROM
  Kreditoren as k
    join Rel_Kreditor_Artikel KAr on k.ID=KAr.Kreditor_ID
    join Artikel             A  on A.ID=KAr.Art_ID
    join Kreditor_Artikel    KA on KA.ID=KAr.Kreditor_Art_ID
    join Rel_Kred_Art_Preise KAPr on KAPr.Kreditor_Art_ID=KA.ID
    Join Kreditor_Preise     KP on KAPr.Kreditor_Preise_ID=KP.ID
where 1=1
  and max(KP.sDatetime)
group by k.irgendwas
Gruß
K-H

daniel775 10. Sep 2017 18:23

AW: Abfrage in Firebird DB über 6 Tabellen
 
Also irgendetwas stimmt an dem Query nicht. Wenn ich "and max(KP.sDatetime)" weglasse, dann bekomme ich zumindest ein Ergebnis. Sonst die Errormessage
"Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 11, column 1.
Group."

p80286 10. Sep 2017 18:30

AW: Abfrage in Firebird DB über 6 Tabellen
 
wenn Du
"Group by k.irgendwas" genutzt hast, dann kann das nicht funktionieren, das ist der Platzhalter für Daten, die du aus der Kreditoren-Tabelle abfragen willst.

Gruß
K-H

daniel775 10. Sep 2017 18:36

AW: Abfrage in Firebird DB über 6 Tabellen
 
Irgendwie hab ich befürchtet das die Antwort kommt. Nein, hab ich natürlich nicht 1:1 genutzt!
sondern:

SELECT k.Firmenname, k.KREDITORNR, KP.datum, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO
FROM
Kreditoren as k
join Rel_Kreditor_Artikel KAr on k.ID = KAr.Kreditor_ID
join Artikel A on A.ID = KAr.Art_ID
join Kreditor_Artikel KA on KA.ID = KAr.Kreditor_Art_ID
join Rel_Kred_Art_Preise KAPr on KAPr.Kreditor_Art_ID = KA.ID
join Kreditor_Preise KP on KAPr.Kreditor_Preise_ID = KP.ID
where 1=1
and max(KP.SDATETIME) as datum
group by k.FIRMENNAME, k.KREDITORNR, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO;


oder


SELECT k.Firmenname, k.KREDITORNR, KP.SDATETIME, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO
FROM
Kreditoren as k
join Rel_Kreditor_Artikel KAr on k.ID = KAr.Kreditor_ID
join Artikel A on A.ID = KAr.Art_ID
join Kreditor_Artikel KA on KA.ID = KAr.Kreditor_Art_ID
join Rel_Kred_Art_Preise KAPr on KAPr.Kreditor_Art_ID = KA.ID
join Kreditor_Preise KP on KAPr.Kreditor_Preise_ID = KP.ID
where 1=1
and max(KP.SDATETIME)
group by k.FIRMENNAME, k.KREDITORNR, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO;


oder

SELECT k.Firmenname, k.KREDITORNR, KP.sdatetime, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO
FROM
Kreditoren as k
join Rel_Kreditor_Artikel KAr on k.ID = KAr.Kreditor_ID
join Artikel A on A.ID = KAr.Art_ID
join Kreditor_Artikel KA on KA.ID = KAr.Kreditor_Art_ID
join Rel_Kred_Art_Preise KAPr on KAPr.Kreditor_Art_ID = KA.ID
join Kreditor_Preise KP on KAPr.Kreditor_Preise_ID = KP.ID
where 1=1
group by k.FIRMENNAME, k.KREDITORNR, KP.sdatetime, KP.LISTENPREIS_NETTO, KP.EKPREIS_NETTO;


wobei ich beim letzten ein Ergebnis habe. Aber eben ohne " and max(KP.sDatetime) "

TBx 10. Sep 2017 18:50

AW: Abfrage in Firebird DB über 6 Tabellen
 
SQL-Code:
where 1=1
  and max(KP.SDATETIME) as datum
sollte da mal korrigiert werden, die erste Zeile enthält eine überflüssige Bedingung, da immer erfüllt und die zweite Zeile enthält nur einen Ausdruck, keine Bedingung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:17 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz