SQL-Abfrage Letzter Wert in WHERE Klausel
Hallo,
ich bräuchte mal bitte eure Hilfe.
In unserem Warenwirtschaftssystem sind die Artikelbestände in 3 verschiedenen Tabellen gespeichert.
In der Tabelle "Artikel" ist der Artikelbestand, in der Tabelle "Lager" der Buchungsbestand und in der Tabelle "LagerB" der Lagerbestand. Natürlich sollte in allen 3 Tabellen der Bestand identisch sein. Jedoch gibt es leider trotzdem ab und zu Artikel, wo dies nicht der Fall ist.
Daher hätte ich gerne eine SQL-Abfrage, wo ich mir zu einem bestimmten Artikel die 3 Bestände anzeigen lassen kann.
Ich habe mir bis jetzt das hier gebastelt:
Das ist an sich schon nicht schlecht. Aber da in der Tabelle "Lager" teilweise viele Werte stehen, je nach Anzahl der Buchungen von dem Artikel, spuckt es mir halt auch soviele Ergebnisse aus:
Ich möchte aber halt, das es mir aus dieser Tabelle nur den Bestand von dem letzten Wert anzeigt. Ich habe es schon mit LAST(Datum) oder MAX(Zaehler) probiert. Aber das funktionierte leider bei mir nicht so wirklich.
Folgende Felder umfasst die Tabelle "Lager":
Das Feld Zaehler ist eine fortlaufende Zahl in der Positionstabelle von allen Aufträgen. Daher wäre die MAX-Funktion da eigentlich am besten. Oder man nimmt die Zeile mit dem letzten Datum.
Ich hoffe, ich konnte mich verständlich ausdrücken und ich hoffe noch mehr, das ihr mir weiterhelfen könnt.
ich bräuchte mal bitte eure Hilfe.
In unserem Warenwirtschaftssystem sind die Artikelbestände in 3 verschiedenen Tabellen gespeichert.
In der Tabelle "Artikel" ist der Artikelbestand, in der Tabelle "Lager" der Buchungsbestand und in der Tabelle "LagerB" der Lagerbestand. Natürlich sollte in allen 3 Tabellen der Bestand identisch sein. Jedoch gibt es leider trotzdem ab und zu Artikel, wo dies nicht der Fall ist.
Daher hätte ich gerne eine SQL-Abfrage, wo ich mir zu einem bestimmten Artikel die 3 Bestände anzeigen lassen kann.
Ich habe mir bis jetzt das hier gebastelt:
SELECT
a.Artikel, a.Artikelnummer, a.Bezeichnung, a.Bestand AS Artikelbestand, b.Bestand AS Buchungsbestand, c.Bestand AS Lagerbestand
FROM
Artikel a
LEFT JOIN
Lager b ON a.Artikel = b.Artikel
LEFT JOIN
LagerB c ON a.Artikel = c.Artikel
WHERE
a.Artikel = '184428' AND c.Ort = '4'
Das ist an sich schon nicht schlecht. Aber da in der Tabelle "Lager" teilweise viele Werte stehen, je nach Anzahl der Buchungen von dem Artikel, spuckt es mir halt auch soviele Ergebnisse aus:
Ich möchte aber halt, das es mir aus dieser Tabelle nur den Bestand von dem letzten Wert anzeigt. Ich habe es schon mit LAST(Datum) oder MAX(Zaehler) probiert. Aber das funktionierte leider bei mir nicht so wirklich.
Folgende Felder umfasst die Tabelle "Lager":
Das Feld Zaehler ist eine fortlaufende Zahl in der Positionstabelle von allen Aufträgen. Daher wäre die MAX-Funktion da eigentlich am besten. Oder man nimmt die Zeile mit dem letzten Datum.
Ich hoffe, ich konnte mich verständlich ausdrücken und ich hoffe noch mehr, das ihr mir weiterhelfen könnt.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 3029506581
Url: https://administrator.de/forum/sql-abfrage-letzter-wert-in-where-klausel-3029506581.html
Ausgedruckt am: 27.12.2024 um 05:12 Uhr
16 Kommentare
Neuester Kommentar
Für dein Problem gibt es mehrere Herangehensweisen die mal besser mal schlechter sind. Ich denke hier wäre es das Beste (und ist generell auch das übersichtlichste), wenn man erstmal nur den aktuellen Lagerbestand betrachtet, also die Tabellen quasi vorfiltert auf aktuell gültige Datensätze. Ich gehe jetzt mal davon aus das der höchste Zähler zu jeder Artikel-ID dem aktuellen Wert entspricht, alle anderen Datensätze sind "historische" Daten. (Oder vertue ich mich da? so ganz sicher bin ich nicht.)
Das müsste eigentlich so schon funktionieren aber sollte natürlich noch sauber ausformuliert werden (zumindest keine *). Eventuell wird auch die Performance schlechter aber das läßt sich eigentlich kaum vermeiden, je nach Datenmenge.
WITH b AS (
SELECT ROW_NUMBER() OVER (PARTITION BY Artikel ORDER BY Zaehler DESC) AS zeile,*
FROM Lager
), c AS (
SELECT ROW_NUMBER() OVER (PARTITION BY Artikel ORDER BY Zaehler DESC) AS zeile,*
FROM LagerB
)
SELECT
a.Artikel, a.Artikelnummer, a.Bezeichnung, a.Bestand AS Artikelbestand, b.Bestand AS Buchungsbestand, c.Bestand AS Lagerbestand
FROM
Artikel a
LEFT JOIN
b ON a.Artikel = b.Artikel AND b.zeile = 1
LEFT JOIN
c ON a.Artikel = c.Artikel AND c.zeile = 1
WHERE
a.Artikel = '184428' AND c.Ort = '4'
Moin,
als Alternative zu dem Vorschlag des Kollegen @ukulele-7
Gruß
em-pie
als Alternative zu dem Vorschlag des Kollegen @ukulele-7
SELECT TOP 1
[Artikel] = a.Artikel
, [Artikelnummer] = a.Artikelnummer
, [Bezeichnung] = a.Bezeichnung
, [Artikelbestand] = a.Bestand
, [Buchungsbestand] = b.Bestand
, [Lagerbestand] = c.Bestand
FROM Artikel a
LEFT JOIN Lager b ON a.Artikel = b.Artikel
LEFT JOIN LagerB c ON a.Artikel = c.Artikel
WHERE a.Artikel = '184428' AND c.Ort = '4'
ORDER BY b.UPDATE desc
Gruß
em-pie
Die Lösung von @em-pie ist noch einfacher und auch gut unter der Voraussetzung das immer genau ein Artikel abgefragt wird. Sobald mehrere Artikel im WHERE-Teil stehen wird es nicht gehen.
Zitat von @ukulele-7:
Die Lösung von @em-pie ist noch einfacher und auch gut unter der Voraussetzung das immer genau ein Artikel abgefragt wird. Sobald mehrere Artikel im WHERE-Teil stehen wird es nicht gehen.
Die Lösung von @em-pie ist noch einfacher und auch gut unter der Voraussetzung das immer genau ein Artikel abgefragt wird. Sobald mehrere Artikel im WHERE-Teil stehen wird es nicht gehen.
Das könnte man mit einer CTE und Grouping by lösen
with cte_Stock as (
SELECT artikel, MAX(update) as update
FROM lager
GROUP BY artikel
)
SELECT
[Artikel] = a.Artikel
, [Artikelnummer] = a.Artikelnummer
, [Bezeichnung] = a.Bezeichnung
, [Artikelbestand] = ISNULL(a.Bestand, 0)
, [Buchungsbestand] = ISNULL(b.Bestand, 0)
, [Lagerbestand] = ISNULL(c.Bestand, 0)
FROM Artikel a
LEFT JOIN Lager b ON a.Artikel = b.Artikel
and b.ARTIKEL = cte_stock.Artikel
and b.UPDATE = cte_stock.Update
LEFT JOIN LagerB c ON a.Artikel = c.Artikel
WHERE a.Artikel = '184428' AND c.Ort = '4'
Ist aber ungetestet
Gruß
em-pie
Aber natürlich, genau dafür ist SQL geschaffen. Dann würde natürlich die Einschränkung auf einen Artikel das ganze wenig nützlich machen daher lasse ich das hier einfach mal weg.
WITH b AS (
SELECT ROW_NUMBER() OVER (PARTITION BY Artikel ORDER BY Zaehler DESC) AS zeile,*
FROM Lager
)
SELECT
a.Artikel, a.Artikelnummer, a.Bezeichnung, a.Bestand AS Artikelbestand, b.Bestand AS Buchungsbestand, c.Bestand AS Lagerbestand
FROM
Artikel a
LEFT JOIN
b ON a.Artikel = b.Artikel AND b.zeile = 1
LEFT JOIN
LagerB c ON a.Artikel = c.Artikel AND c.zeile = 1
WHERE
c.Ort = '4'
AND ( isnull(a.Bestand,0) != isnull(b.Bestand,0)
OR isnull(a.Bestand,0) != isnull(c.Bestand,0) )
Moin,
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
Und noch eine Frage zum Lagerbestand: Du schreibst, da ist kein filtern nötig, weil es durch die Einschränkung auf den Ort eindeutig ist. Aber wenn es mehrere Lagerorte gibt, müßtest Du nicht dann die Menge aller Lagerorte summieren, bevor Du sie mit den anderen beiden Mengen vergleichst? Oder ist Ort '4' ein Pseudolagerort, der die Summe angibt?
Gruß, Mad Max
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
Und noch eine Frage zum Lagerbestand: Du schreibst, da ist kein filtern nötig, weil es durch die Einschränkung auf den Ort eindeutig ist. Aber wenn es mehrere Lagerorte gibt, müßtest Du nicht dann die Menge aller Lagerorte summieren, bevor Du sie mit den anderen beiden Mengen vergleichst? Oder ist Ort '4' ein Pseudolagerort, der die Summe angibt?
Gruß, Mad Max
Zitat von @MadMax:
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
Muss ich dir beipflichten. Wobei mir das so bekannt vorkommt. Ist das Pervasive?
Normale SELECT Statements sind kein Problem. CTE etc. würden je nach Ableger ander aussehen, bzw. nicht existent sein. Das solltest du wirklich mal kurz kundtun.
Generell löst das aber dein Problem nicht ganz: Die Werte gehen auseinander, weil Transaktionen nicht sauber abgeschlossen wurden. INSERT oder UPDATE Fehler. Wenn das oft vorkommt wäre die Frage nach dem warum? Wäre alles in einer Transkation müsste es passen, bzw. sauber zurück gerollt werden. Vermute separate Task. Wenn es dann hängen bleibt wird Rest nicht sauber aktualisiert.
Vlt. mal den MA auf die Finger schauen, ob die die Masken Eingaben irgendwo abbrechen können und die Fehlbestände verursachen? Wenn die Software nicht abstürzt ist die Ursache meist eine unsaubere Programmierung.
Zitat von @MadMax:
Moin,
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
Zweifelsfrei konnte man am ersten Post schon erkennen, dass es ein SQL-Server ist.Moin,
hier wird ja schon feste mit Abfragen hantiert, aber was ist das eigentlich für eine Datenbank, habe ich das übersehen? Ukulele geht offensichtilch von einem SQL-Server aus, em-pie hat sich vornehm zurückgehalten und die Abfrage recht allgemein gehalten.
Wäre es NoSQL gewesen, sähe das sicherlich auf den Screenshots anders aus
Fernab kommt hier im Board gefühlt in 80% der Fälle ein MS SQL-Server zum Einsatz. Die Trefferquote ist somit recht hoch, auf anhieb den MS SQL-Dialekt zu treffen.
Beide Statements (der von @ukulele-7 und mir) funktionieren aber mit MySQL/ MariaDB sowie MS SQL.
Bei einer DB2 oder einer Oracle DB sieht das dann wiederum anders aus.
Postgres nicht vergessen, sonst wird @akretschmer sauer.
Bei Access könnte es Probleme geben, aber nur mit der Syntax. Das Query im WITH.-Teil kann man auch als Subquery schreiben, nur ROW_NUMBER() ist in wenigen SQL-DBs ein Problem.
Bei Access könnte es Probleme geben, aber nur mit der Syntax. Das Query im WITH.-Teil kann man auch als Subquery schreiben, nur ROW_NUMBER() ist in wenigen SQL-DBs ein Problem.
Wenn Sie Ihre Situation genau betrachten, können Sie sehen, dass Sie einerseits den Vorteil haben, Daten in verschiedenen Tabellen zu halten, andererseits aber auch die Herausforderung haben, solche verstreuten Daten zu durchsuchen.
SELECT COUNT(*),_topRecord
FROM subArticles
GROUP BY _topRecord?