MySQL - Kleinster Wert aus mehreren Tabellen
Hallo,
ich habe identische Daten von mehreren Lieferanten in mehreren Tabellen einer MySQL 5 Datenbank. Jetzt muss ich aus allen Tabellen den kleinsten Preis ermitteln.
Meine bisherige Abfrage funktioniert schon soweit.
Mit Hilfe der Funktion Greatest() wird ein Preisaufschlag zu dem Preis "vk_preis" berechnet. Bisher kam der Preis aus der Tabelle db.tb1.vk_preis, jetzt soll es aber der kleinste Preis aus allen Tabellen sein (db.tb1.vk_preis, db.tb2.vk_preis, db.tb3.vk_preis, db.tb4.vk_preis...)
Ich denke das muss ich über min() machen. Aber irgendwie komme ich jetzt nicht drauf, wo ich das da einbauen soll.
Nachfolgend habe ich begonnen die Abfrage anzupassen. Ab Greatest ist noch alles wie es bisher war und es auch funktioniert:
select distinct
db.tb1.id,
db.tb1.anz_tu,
db.tb1.breite,
db.tb1.hersteller,
db.tb1.lager,
db.tb1.vk_preis,
db.tb1.art_nr,
db.rs_preis_calc.von_preis,
db.rs_preis_calc.bis_preis,
db.rs_preis_calc.euro_aufschlag,
db.rs_preis_calc.proz_aufschlag,
db.tb2.art_nr as tb2_art_nr,
db.tb2.lager as tb2_lager,
db.tb2.vk_preis as tb2_vk_preis,
db.tb3.art_nr as tb3_art_nr,
db.tb3.lager as tb3_lager,
db.tb3.vk_preis as tb3_vk_preis,
db.tb4.art_nr as tb4_art_nr,
db.tb4.lager as tb4_lager,
db.tb4.vk_preis as tb4_vk_preis,
db.tb5.art_nr as tb5_art_nr,
db.tb5.lager as tb5_lager,
db.tb5.vk_preis as tb5_vk_preis,
db.tb6.art_nr as tb6_art_nr,
db.tb6.lager as tb6_lager,
db.tb6.vk_preis as tb6_vk_preis,
GREATEST(if (euro_aufschlag>0 and db.tb1.vk_preis > 0 , (db.tb1.vk_preis*1) + euro_aufschlag, 0),
if (proz_aufschlag>0, (
db.tb1.vk_preis*1)+(db.tb1.vk_preis*(proz_aufschlag/100)), 0),
db.tb1.vk_preis) AS akpreis,
GREATEST(if (euro_aufschlag>0 , (db.tb1.vk_preis*1) + euro_aufschlag, 0),
if (proz_aufschlag>0, (
db.tb1.vk_preis*1)+(db.tb1.vk_preis*(proz_aufschlag/100)), 0),
db.tb1.vk_preis) AS vkpreis
from db.rs_preis_calc, db.tb1
left join db.tb2 on db.tb1.art_nr = db.tb2.art_nr
left join db.tb3 on db.tb1.art_nr = db.tb3.art_nr
left join db.tb4 on db.tb1.art_nr = db.tb4.art_nr
left join db.tb5 on db.tb1.art_nr = db.tb5.art_nr
left join db.tb6 on db.tb1.art_nr = db.tb6.art_nr
where ((db.tb1.art_nr is not null) and (
db.tb1.vk_preis > von_preis) and (
db.tb1.vk_preis <= bis_preis) and (
999999 = db.rs_preis_calc.id) and (
0 = db.rs_preis_calc.preisgruppe)and (
db.tb1.anz_tu = '120') and (
db.tb1.breite = '2155'))
order by
db.tb1.hersteller,
db.tb1.breite
Die Stellen ala "db.tb2.vk_preis as tb2_vk_preis," habe ich jetzt schon für die Preisermittlung eingefügt. Weiter komme ich jetzt nicht.
Die Frage ist nun, wie bekomme ich den geringsten Preis aus allen Tabellen und zwar so, das auf diesen noch der Aufschlag addiert werden.
Hat jemand einen Tipp für mich?
Vielen Dank schon mal und die besten Grüße
Marcel
ich habe identische Daten von mehreren Lieferanten in mehreren Tabellen einer MySQL 5 Datenbank. Jetzt muss ich aus allen Tabellen den kleinsten Preis ermitteln.
Meine bisherige Abfrage funktioniert schon soweit.
Mit Hilfe der Funktion Greatest() wird ein Preisaufschlag zu dem Preis "vk_preis" berechnet. Bisher kam der Preis aus der Tabelle db.tb1.vk_preis, jetzt soll es aber der kleinste Preis aus allen Tabellen sein (db.tb1.vk_preis, db.tb2.vk_preis, db.tb3.vk_preis, db.tb4.vk_preis...)
Ich denke das muss ich über min() machen. Aber irgendwie komme ich jetzt nicht drauf, wo ich das da einbauen soll.
Nachfolgend habe ich begonnen die Abfrage anzupassen. Ab Greatest ist noch alles wie es bisher war und es auch funktioniert:
select distinct
db.tb1.id,
db.tb1.anz_tu,
db.tb1.breite,
db.tb1.hersteller,
db.tb1.lager,
db.tb1.vk_preis,
db.tb1.art_nr,
db.rs_preis_calc.von_preis,
db.rs_preis_calc.bis_preis,
db.rs_preis_calc.euro_aufschlag,
db.rs_preis_calc.proz_aufschlag,
db.tb2.art_nr as tb2_art_nr,
db.tb2.lager as tb2_lager,
db.tb2.vk_preis as tb2_vk_preis,
db.tb3.art_nr as tb3_art_nr,
db.tb3.lager as tb3_lager,
db.tb3.vk_preis as tb3_vk_preis,
db.tb4.art_nr as tb4_art_nr,
db.tb4.lager as tb4_lager,
db.tb4.vk_preis as tb4_vk_preis,
db.tb5.art_nr as tb5_art_nr,
db.tb5.lager as tb5_lager,
db.tb5.vk_preis as tb5_vk_preis,
db.tb6.art_nr as tb6_art_nr,
db.tb6.lager as tb6_lager,
db.tb6.vk_preis as tb6_vk_preis,
GREATEST(if (euro_aufschlag>0 and db.tb1.vk_preis > 0 , (db.tb1.vk_preis*1) + euro_aufschlag, 0),
if (proz_aufschlag>0, (
db.tb1.vk_preis*1)+(db.tb1.vk_preis*(proz_aufschlag/100)), 0),
db.tb1.vk_preis) AS akpreis,
GREATEST(if (euro_aufschlag>0 , (db.tb1.vk_preis*1) + euro_aufschlag, 0),
if (proz_aufschlag>0, (
db.tb1.vk_preis*1)+(db.tb1.vk_preis*(proz_aufschlag/100)), 0),
db.tb1.vk_preis) AS vkpreis
from db.rs_preis_calc, db.tb1
left join db.tb2 on db.tb1.art_nr = db.tb2.art_nr
left join db.tb3 on db.tb1.art_nr = db.tb3.art_nr
left join db.tb4 on db.tb1.art_nr = db.tb4.art_nr
left join db.tb5 on db.tb1.art_nr = db.tb5.art_nr
left join db.tb6 on db.tb1.art_nr = db.tb6.art_nr
where ((db.tb1.art_nr is not null) and (
db.tb1.vk_preis > von_preis) and (
db.tb1.vk_preis <= bis_preis) and (
999999 = db.rs_preis_calc.id) and (
0 = db.rs_preis_calc.preisgruppe)and (
db.tb1.anz_tu = '120') and (
db.tb1.breite = '2155'))
order by
db.tb1.hersteller,
db.tb1.breite
Die Stellen ala "db.tb2.vk_preis as tb2_vk_preis," habe ich jetzt schon für die Preisermittlung eingefügt. Weiter komme ich jetzt nicht.
Die Frage ist nun, wie bekomme ich den geringsten Preis aus allen Tabellen und zwar so, das auf diesen noch der Aufschlag addiert werden.
Hat jemand einen Tipp für mich?
Vielen Dank schon mal und die besten Grüße
Marcel
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 86341
Url: https://administrator.de/contentid/86341
Ausgedruckt am: 22.11.2024 um 21:11 Uhr
13 Kommentare
Neuester Kommentar
Hallo,
ich kenne mich mit MySQL nicht wirklich aus. Aber unter MSSQL würde ich eine Stored Procedure erstellen, die aus jeder Tabelle den kleinsten Wert auswählen und in temporäre Tabelle einführt. Danach dann halt aus der den kleinsten auswählen...
Wobei... SELECT min(preis) FROM (Select min(preis) From a UNION Select min(preis) FROM b ....) sollte eigentlich passen und auch nicht wirklich unelegant sein.
Gruß
Filipp
ich kenne mich mit MySQL nicht wirklich aus. Aber unter MSSQL würde ich eine Stored Procedure erstellen, die aus jeder Tabelle den kleinsten Wert auswählen und in temporäre Tabelle einführt. Danach dann halt aus der den kleinsten auswählen...
Wobei... SELECT min(preis) FROM (Select min(preis) From a UNION Select min(preis) FROM b ....) sollte eigentlich passen und auch nicht wirklich unelegant sein.
Gruß
Filipp
Moin Marcel.
die Struktur Deiner Tabellen (und wie es soweit kommen konnte) ist mir etwas unklar.
Wenn ich es richtig lese, gibt es EINE Tabelle tbl, in der sich alle denkbaren Artikel
Ich hoffe, ich habe das ganz falsch verstanden, aber dann schildere doch bitte nochmal den Sachverhalt bzw. die (grobe) Struktur der Tabellen.
Insbesondere ob diese "tbl" wirklich alle Artikel enthält oder ob es auch sein kann, dass es Artikel 4711 nur in tbl2 oder tbl4 gibt und nicht in "tbl".
Grüße
Biber
die Struktur Deiner Tabellen (und wie es soweit kommen konnte) ist mir etwas unklar.
Wenn ich es richtig lese, gibt es EINE Tabelle tbl, in der sich alle denkbaren Artikel
- sowohl mit den Stammdaten-Attribute wie Länge, Breite, Höhe, Gewicht etc
- als auch den Lager/Bestandsinfo
- als auch den Preis/Zuschlags/Kalkulationsdaten befinden
- und die Artikel-ID gilt genauso wie die Stammdaten-Attribute datenbankweit in weiteren x Tabellen????
Ich hoffe, ich habe das ganz falsch verstanden, aber dann schildere doch bitte nochmal den Sachverhalt bzw. die (grobe) Struktur der Tabellen.
Insbesondere ob diese "tbl" wirklich alle Artikel enthält oder ob es auch sein kann, dass es Artikel 4711 nur in tbl2 oder tbl4 gibt und nicht in "tbl".
Grüße
Biber
Moin Marcel,
IMHO ist Dein oben gepostetes Statement fachlich falsch, wenn sich nicht unbedingt alle Artikel(-IDs) in der tbl1 befinden müssen.
Ich würde eher mit einem UNION ALL ansetzen, wie schon filippg geschrieben hat.
In dem Union sollten alle Felder enthalten sein, die Du für Anzeige, weitere Berechnungen oder die WHERE-Klausel brauchst. Sowie ein weiteres Feld, das Dir den Quelltabellennamen angibt.
Also sinngemäß:
Grüße
Biber
IMHO ist Dein oben gepostetes Statement fachlich falsch, wenn sich nicht unbedingt alle Artikel(-IDs) in der tbl1 befinden müssen.
Ich würde eher mit einem UNION ALL ansetzen, wie schon filippg geschrieben hat.
In dem Union sollten alle Felder enthalten sein, die Du für Anzeige, weitere Berechnungen oder die WHERE-Klausel brauchst. Sowie ein weiteres Feld, das Dir den Quelltabellennamen angibt.
Also sinngemäß:
SELECT First( allTb.Id) , min(allTb.VK_preis), First(AllTb.QuellTab)
FROM
( Select tb1.id, tb1.breite, tb1.vk_preis, "TB1" as QuellTab from tb1
UNION All
Select tb2.id, tb2.breite, tb2.vk_preis, "TB2" from tb2
Union all
Select tb3.id, tb3.breite, tb3.vk_preis, "TB3" from tb3
) as AllTb
Where Alltb.breite = 123;
Grüße
Biber
Hallo,
ich hatte da gleich in meinem Ansatz einen Fehler, bin ich gestern zufällig auch drauf gestoßen:
Ein "Select ... FROM (Select...)" ist (zumindest in MS SQL) nicht zulässig. Würde auch zu deiner Fehlermeldung passen.
Ich habe mir dann beholfen, indem ich aus dem inneren Select (also hier die ganzen UNIONs) ein View gemacht habe, auf den kann ich auch wieder ein Select anwenden. Hat mich ein wenig gewundert, ist glaube ich letztlich auch lediglich eine Syntax-Frage, und nicht eine Problem fehlender Funktionalität.
Gruß
Filipp
ich hatte da gleich in meinem Ansatz einen Fehler, bin ich gestern zufällig auch drauf gestoßen:
Ein "Select ... FROM (Select...)" ist (zumindest in MS SQL) nicht zulässig. Würde auch zu deiner Fehlermeldung passen.
Ich habe mir dann beholfen, indem ich aus dem inneren Select (also hier die ganzen UNIONs) ein View gemacht habe, auf den kann ich auch wieder ein Select anwenden. Hat mich ein wenig gewundert, ist glaube ich letztlich auch lediglich eine Syntax-Frage, und nicht eine Problem fehlender Funktionalität.
Gruß
Filipp
Moin Marcel und filippg,
hätte ich vielleicht dazuschreiben müssen, dass ich nichts an einem (MySQL-)Server getestet habe. Und ich denke, dass fillipg mit seiner Analyse Recht hat.
Also pack das innere Select in einen eigenen VIEW:
Ich habe hier den möglichen VIEW noch um ein, zwei Felder erweitert, die vielleicht als mögliche Kriterien sinnvoll sein könnten (Anz_Tu, Lager..).
Im Prinzip könnten alle Tabellenfelder in den VIEW, die in allen Tbx-Tabellen vorhanden sind.
Nur.... eigentlich erscheint es mir zunehmend fragwürdiger, welche Existenzberechtigung diese vielen Tabellen gleichen Aufbaus überhaupt haben.
Eine Tabelle (ggf. mit einem Zusatzfeld "QuellTab" oder "Lieferant" oder was immer fachlich diese TBs unterschiedlich macht wäre sinnvoller.
Anyhow, erstmal ausgehend von dem, was wir jetzt haben wäre der zweite Schritt:
... wobei, fällt mir grad auf, dieses Statement das falsche Ergebnis liefern dürfte, falls in mehreren QuellTabs der gleiche "minimale" Preis steht.
Na gut, machen wir im nächsten Step - probier bitte erstmal diesen Zwischenschritt.
Grüße
Biber
hätte ich vielleicht dazuschreiben müssen, dass ich nichts an einem (MySQL-)Server getestet habe. Und ich denke, dass fillipg mit seiner Analyse Recht hat.
Also pack das innere Select in einen eigenen VIEW:
CREATE VIEW AllTb (ArtID, Breite, VK_Preis, QuellTab, Anz_tu, Lager) AS
(Select tb1.id, tb1.breite, tb1.vk_preis, "TB1" as QuellTab , tb1.anz_tu, tb1.Lager from datenbank.tabelle1 as tb1
Union all
Select tb2.id, tb2.breite, tb2.vk_preis, "TB2" , tb2.anz_tu, tb2.Lager from datenbank.tabelle2 as tb2
Union all
Select tb3.id, tb3.breite, tb3.vk_preis, "TB3" , tb3.anz_tu, tb3.Lager from datenbank.tabelle3 as tb3
)
Ich habe hier den möglichen VIEW noch um ein, zwei Felder erweitert, die vielleicht als mögliche Kriterien sinnvoll sein könnten (Anz_Tu, Lager..).
Im Prinzip könnten alle Tabellenfelder in den VIEW, die in allen Tbx-Tabellen vorhanden sind.
Nur.... eigentlich erscheint es mir zunehmend fragwürdiger, welche Existenzberechtigung diese vielen Tabellen gleichen Aufbaus überhaupt haben.
Eine Tabelle (ggf. mit einem Zusatzfeld "QuellTab" oder "Lieferant" oder was immer fachlich diese TBs unterschiedlich macht wäre sinnvoller.
Anyhow, erstmal ausgehend von dem, was wir jetzt haben wäre der zweite Schritt:
SELECT First(ArtId) , min(VK_preis), First(QuellTab)
FROM AllTB
Where Alltb.Breite = 123
Na gut, machen wir im nächsten Step - probier bitte erstmal diesen Zwischenschritt.
Grüße
Biber
Mein Gott, jetzt stell dich halt nicht so an. Wie du sicher schon festgestellt hast besteht das ganze Statement aus mehreren Komponenten. Probiere halt mal eins von den Selects alleine. Dann mal zwei mit Union, dann... manchmal muss man sich an den Fehler halt rantasten.
Das "datenbank.tabelle1 as tb1" legt eine Alias fest, danach soll "tabelle1" auch unter "tb1" ansprechbar sein. Sonst müsste es davor auch "Select tabelle1.id, tabelle1.breite,..." statt "Select tb1.id, tb1.breite, ..." heißen. Ich könnte mir auch vorstellen, dass hier der Fehler liegt. Wenn man einen Alais für Tabellen festlegt muss man das "AS" glaube ich weglassen, dass ist nur für Aliase für Spalten.
Gruß
Filipp
Das "datenbank.tabelle1 as tb1" legt eine Alias fest, danach soll "tabelle1" auch unter "tb1" ansprechbar sein. Sonst müsste es davor auch "Select tabelle1.id, tabelle1.breite,..." statt "Select tb1.id, tb1.breite, ..." heißen. Ich könnte mir auch vorstellen, dass hier der Fehler liegt. Wenn man einen Alais für Tabellen festlegt muss man das "AS" glaube ich weglassen, dass ist nur für Aliase für Spalten.
Gruß
Filipp
@Marcel
... und wie Filipp schon geschrieben hat, ist es am ehesten durch Probieren zu lösen.
Da ich hier im Moment auch kein mySQL im Zugriff habe, bleibt mir auch nur Raten oder Suchmaschine - Ausprobieren entfällt.
Was eventuell außer dem "AS" oder "nicht AS"-Tabellenname sein kann ist, dass die Inhalte "TB1","TB2"... in einfache statt in doppelte Anführungszeichen gehören.
Grüße
Biber
... und wie Filipp schon geschrieben hat, ist es am ehesten durch Probieren zu lösen.
Da ich hier im Moment auch kein mySQL im Zugriff habe, bleibt mir auch nur Raten oder Suchmaschine - Ausprobieren entfällt.
Was eventuell außer dem "AS" oder "nicht AS"-Tabellenname sein kann ist, dass die Inhalte "TB1","TB2"... in einfache statt in doppelte Anführungszeichen gehören.
Eine Frage hierzu: Was genau bewirkt eigentlich "TB1", "TB2" und "TB3" in den Selects?
Damit will ich nur ein künstliches Feld in dem View haben, aus dem ich erkennen kann, aus welcher Ursprungstabelle der gefundene Artikel stammt.Grüße
Biber