Lösung Cursor?

oder entgeht mir hier irgendwas?
Dein vereinfachtes Statement würde- so wie ich die Anforderung verstehe- grob gesehen funktionieren, wenn man es als Subselect in ein Hauptselect einbaut, so ungefähr wie der Funktionsaufruf als Teil des Hauptselects in dem letzten Schritt des 2. dbfiddle. Dazu müsste aber noch dateid in die Ausgabe (Select clause) rein, damit es vollständig gejoint werden kann. Dann hakt es wahrscheinlich mit der Aggregation.

Es ist halt keine klassische Mengenoperation, sondern eine Zielwertsuche, die an den Parametern werks, matnr und dateid hängt.
 
Werbung:
Da ich mich mir Funktion nicht so gut auskenne (ist aber auf meine ToDo Liste mit Dingen die ich noch gerne lernen möchte) würde ich zunächst einmal den Ansatz von @ukulele eingehen wollen. Das Ergebnis von 4 verstehe ich nicht, wenn ich Warenausgänge von 11 in der ersten, 10 in der zweiten und 9 in der dritten Woche habe, sind die 23 Stück auf Lager doch schon nach 3 Wochen und nicht nach 4 Wochen weg, davon abgesehen ist es auch nur ein Ergebnis und nicht für jede Zeile ein Ergebnis, weshalb ich dachte das Cursor die Lösung ist. Den dann würde hoffentlich in der ersten Zeile als Ergebnis stehen 3 in der zweiten dann 47 weil dann keine weiteren Eintragungen vorhanden sind und die Warenausgänge nicht ausreichen um den Warenbestand zu verzerren. In der 3 Zeile würde dann wieder 46 stehen, in der 4. dann 17 usw.
 
Das Ergebnis von 4 verstehe ich nicht, wenn ich Warenausgänge von 11 in der ersten, 10 in der zweiten und 9 in der dritten Woche habe, sind die 23 Stück auf Lager doch schon nach 3 Wochen und nicht nach 4 Wochen weg, davon abgesehen ist es auch nur ein Ergebnis und nicht für jede Zeile ein Ergebnis, weshalb ich dachte das Cursor die Lösung ist. Den dann würde hoffentlich in der ersten Zeile als Ergebnis stehen 3 in der zweiten dann 47 weil dann keine weiteren Eintragungen vorhanden sind und die Warenausgänge nicht ausreichen um den Warenbestand zu verzerren. In der 3 Zeile würde dann wieder 46 stehen, in der 4. dann 17 usw.
Sry ich hab mir die Testdaten jetzt mal in eine Tabelle gepackt, ich hab das vorher nicht getestet - das ist ja auch Arbeit. Was meinst du mit "das Ergebnis von 4"? - vermutlich WRKS 1010 MATNR 59025.

dateid Total_Menge_FERT_ABC WERKS MATNR WA_Menge_FERT runtotal WA_Menge_FERT_count#
----------- -------------------- ----------- ----------- --------------------------------------- --------------------------------------- --------------------
20230626 23 1010 59025 11.000 11.000 1
20230703 133 1010 59025 10.000 21.000 2
20230710 124 1010 59025 9.000 30.000 3
20230717 44 1010 59025 19.000 61.000 4
20230717 0 1010 59025 12.000 61.000 5
20230724 0 1010 59025 6.000 67.000 6
20230731 0 1010 59025 6.000 73.000 7
20230814 0 1010 59025 4.000 81.000 8
20230814 0 1010 59025 4.000 81.000 9
20230821 0 1010 59025 0.000 81.000 10

Richtig, ausgehend davon das WA_Menge_FERT dem entspricht was in dieser Woche produziert wurde dann sind in Woche 3 23 Einheiten erreicht und mit 30 sogar übererfüllt, soweit so klar.

Ich ging jetzt davon aus das Total_Menge_FERT_ABC über WRKS 1010 MATNR 59025 eindeutig ist und dieser gesuchten Menge entspricht, sich aber nicht verändert, das ist ganz offensichtlich nicht der Fall.

Woher weiß ich denn jetzt welche Menge ich suche, heißt Total_Menge_FERT_ABC das ich in der ersten Woche 23 Bedarf habe und dieser dann in Woche 2 auf 133 steigt oder kommen in Woche 2 nochmal 133 dazu oder wie genau ist diese Spalte zu verstehen, das ist mir nicht klar. Du brauchst vermutlich noch einen running total auf den Bedarf und dann könnte der Bedarf ja auch wieder erneut das produzierte Volumen übersteigen. Ich muss also erstmal verstehen was sich hinter der Spalte verbirgt.
 
Die Spalte Total_Menge_FERT_ABC gibt an welche Menge auf Lager verfügbar sein. Die von dir verwendeten Daten schein nicht der letzten von mir zur Verfügung gestellten Datei zu entsprechen, weil es eigentlich keine doppelten Werte (Dateid, MATNR & WERKS) in Kombination geben. Ich suche die Anzahl der Wochen, basierend auf DateID, die das Material verfügbar ist, wenn ich nur die Spalte WA_Menge_FERT jeweils abziehe. Es kommt also ein Wert zwischen 1 und 52 raus.
 
Okay meine Daten habe ich angepasst.

Ich habe dann jetzt
Code:
SELECT    dateid,
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        sum(WA_Menge_FERT) over(partition by werks, matnr order by dateid)  AS running_total,
        row_number() over(partition by werks, matnr order by dateid) AS woche
FROM    tabelle
ORDER BY WERKS, MATNR, dateid
dateid Total_Menge_FERT_ABC WERKS MATNR WA_Menge_FERT running_total woche
----------- ------------------------ ----------- ----------- --------------------------------------- --------------------------------------- --------------------
20230626 23 1010 59025 11.000 11.000 1
20230703 133 1010 59025 10.000 21.000 2
20230710 124 1010 59025 9.000 30.000 3
20230717 115 1010 59025 9.000 39.000 4
20230724 107 1010 59025 8.000 47.000 5
20230731 99 1010 59025 8.000 55.000 6
20230807 82 1010 59025 17.000 72.000 7
20230814 62 1010 59025 20.000 92.000 8
20230821 63 1010 59025 19.000 111.000 9
20230828 44 1010 59025 19.000 130.000 10

Nochmal zu meinem Verständnis:
- Total_Menge_FERT_ABC ist der Lagerbestand
- WA_Menge_FERT ist nicht eine Menge die produziert wird sondern die Menge die das Lager verlässt

Du willst jetzt in Datensatz 1 wissen wie lange es dauert (in Wochen) bis die Menge 23 das Lager verlassen hat (3 Wochen) und in Datensatz 2 dann wie lange es gedauert hat bis die Menge 133 das Lager verlassen hat, richtig?

Das ist deutlich komplexer als ich annahm. Auch gefallen mir die Ausgangsdaten eigentlich nicht, das ist ja vermutlich schon irgendwie aggregiert aber brechnen lässt es sich natürlich. Was passiert denn mit dem Rest 7 aus Datensatz 1 Woche 3. Geht es dann erst los das die 133 aus Datensatz 2 abgearbeitet werden?
 
Da ich mich mir Funktion nicht so gut auskenne
Tja, Du kannst einfach das fiddle nehmen und Deine neuen Daten dort reinkopieren. Es beißt nicht. Du musst dabei nicht mal was lernen. Einfach nur benutzen. Die Funktion ist ok. Du kannst sie dort rauskopieren und bei Dir einsetzen.

Das ist deutlich komplexer als ich annahm
Du kannst nicht mit einem Single Run Statement die Totals produzieren und den Vergleichswert mitführen. Das ginge nur, per Windows Functions, wenn der Vergleichswert einen konstanten Abstand zum running total hätte. Das ist ja das interessante an der Anforderung. Es müssen 2 verschiedene Select sein.
Wie gesagt, die Function ist ok, das Beispielstatement hinkt etwas, weil es aus meinem ersten Versuch mit wenig Daten stammt.
 
Richtig, mit einem Durchlauf geht es (vermutlich) nicht, aber um sicher zu sein wollte ich das erst mal ganz genau verstehen. Ich verstehe es so das es quasi eine Charge gibt Total_Menge_FERT_ABC. Jede Woche kommt eine neue Charge und die entspricht immer genau dem Wert von Total_Menge_FERT_ABC, also das was neu ist gleich Total_Menge_FERT_ABC, nicht das was noch da ist und was neu hinzugekommen ist. Fertige Chargen werden immer nach FIFO Prinzip (first in, first out) abverkauft / verbraucht wie auch immer. Wenn ich jetzt für jede Charge wissen will wann diese vollständig abverkauft wurde muss ich WA_Menge_FERT von Total_Menge_FERT_ABC des ersten Datensatzes abziehen. WA_Menge_FERT entspricht immer genau dem Wert der in dieser Woche abverkauft wurde.

Beim zweiten Datensatz wird es dann aber kompliziert. Es darf nicht WA_Menge_FERT aus dem selben Datensatz abgezogen werden sondern man muss mit dem Rest aus Datensatz 3 beginnen, sofern wir wirklich FIFO machen und meine Annahmen korrekt sind.

Wenn dem so ist dann würde ich das eventuell mit CTE versuchen, müsste man mal tüfteln. Vor allem aber stehen die beiden Spalten eigentlich in keinerlei Beziehung zu einander, was verwirrend ist weil sie ja in der selben Ausgangstabelle stehen. Und vor allem will ich mir nicht den Kopf zerbrechen um dann fest zu stellen das ich noch was nicht verstehe....
 
Ich versuche das einmal zu ordnen.
Du willst jetzt in Datensatz 1 wissen wie lange es dauert (in Wochen) bis die Menge 23 das Lager verlassen hat (3 Wochen) und in Datensatz 2 dann wie lange es gedauert hat bis die Menge 133 das Lager verlassen hat, richtig?
Genau so ist es. Dabei muss sich keine Gedanken gemacht werden ob es ein Restbestand gibt. Heißt die 23 Stück reichen für 3 Wochen, die verbleibenden 4 Stück sind egal. In der nächsten Zeile soll dann nur von den 133 Stück ohne den Rest der vorherigen Zeile ausgegangen werden. Wichtig ist nur das man immer darauf achtet das diese Berechnung immer berücksichtigt das WERKS und MATNR als eine Partition betrachtet werden.
 
Okay es geht also nicht darum wie lange es dauert bis eine konkrete Menge aus dem Lager auch konkret das Lager verlässt sondern wie lange es dauert eine konkrete Menge theoretisch auszuliefern wenn zuvor kein Bestand vorhanden wäre sondern diese Menge einfach mit der Nachfrage abgearbeitet wird. Ist vielleicht nicht optimal ausgedrückt aber so verstehe ich es, gibt es bestimmt auch einen genauen Fachbegriff und eine Formel für etc.

Das ist mit CTE eigentlich kein Problem. Je nach Daten kann es natürlich zu sehr vielen Rekursionen / Durchläufen kommen wenn z.B. eine besonders große Menge besonders lange brauchen würde, das fängt man am besten ab.

Auch nutze ich beim Join um den nächsten Datensatz in der Reihe zu holen das Datum + 7 Tage, dazu muss ich aus DateID ein vernünftiges Datum machen. Aber es ist ja auch ganz offensichtlich eins nur in einem beknackten Format. Es ginge noch mit einer ROW_NUMBER() vorab, das hätte auch Vorteile wenn tatsächlich mal was doppelt in den Daten steht aber ich finde das nicht so elegant.
Code:
WITH t0 AS (
--t0 dient einzig und allein dazu aus DateID ein brauchbares Datum zu machen
SELECT    WERKS,
        DateID,
        dateadd(day,convert(INT,right(convert(CHAR(8),DateID),2))-1,
        dateadd(month,convert(INT,right(left(convert(CHAR(8),DateID),6),2))-1,
        dateadd(year,convert(INT,left(convert(CHAR(8),DateID),4))-1900,0)
        )) AS [Date],
        MATNR,
        cast(Total_Menge_FERT_ABC AS INT) AS Total_Menge_FERT_ABC,
        cast(WA_Menge_FERT AS INT) AS WA_Menge_FERT
FROM    tabelle
), t1 AS (
--Basis vom CTE
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        Total_Menge_FERT_ABC - WA_Menge_FERT AS rest,
        1 AS [count]
FROM    t0
UNION ALL
--Rekursion vom CTE
SELECT    t1.DateID,
        t1.[Date],
        t1.Total_Menge_FERT_ABC,
        t1.WERKS,
        t1.MATNR,
        t1.WA_Menge_FERT,
        t1.rest - t0.WA_Menge_FERT AS rest,
        t1.[count] + 1 AS [count]
FROM    t1
INNER JOIN t0
ON        t1.WERKS = t0.WERKS
AND        t1.MATNR = t0.MATNR
AND        dateadd(day,t1.[count] * 7,t1.[Date]) = t0.[Date]
--der max(count) ist später interessant, also beim letzten Datensatz count = gesuchter Wert
WHERE    t1.rest > 0
--bei count = 99 dauert es dann 99 Wochen oder länger, hier wird eine Endlosrekursion verhindert und die Performance kann verbessert werden in dem Härtefälle nicht weiter durchgerechnet werden
AND        t1.[count] + 1 <= 99
)
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
--        rest,
        [count] AS gesuchter_Wert
FROM    t1
WHERE    rest <= 0
ORDER BY WERKS, MATNR, [Date], [count]

DateID Date Total_Menge_FERT_ABC WERKS MATNR WA_Menge_FERT gesuchter_Wert
----------- ----------------------- -------------------- ----------- ----------- ------------- --------------
20230626 2023-06-26 00:00:00.000 23 1010 59025 11 3
20230703 2023-07-03 00:00:00.000 133 1010 59025 10 10
20230710 2023-07-10 00:00:00.000 124 1010 59025 9 9
20230717 2023-07-17 00:00:00.000 115 1010 59025 9 8
20230724 2023-07-24 00:00:00.000 107 1010 59025 8 7
20230731 2023-07-31 00:00:00.000 99 1010 59025 8 6
20230807 2023-08-07 00:00:00.000 82 1010 59025 17 5
20230814 2023-08-14 00:00:00.000 62 1010 59025 20 4
20230821 2023-08-21 00:00:00.000 63 1010 59025 19 4
20230828 2023-08-28 00:00:00.000 44 1010 59025 19 3

 
Zuletzt bearbeitet:
@ukulele das hat ein wenig gedauert bevor ich zumindest ein wenig Verstanden haben was da passiert. Mir war nicht bewusst das etwas auf sich selbst in einem Subselect referenzieren kann. Das sorgt für ein ganz schönes Wirrwarr im Kopf.

Noch scheinen dort aber drei größere Problem zu bestehen.
- Zum einen wird die MATNR 59025 in WERK 1044 komplett rausgefiltert, weil es dort keinen Rest von <=0 gibt.
- Zum anderen stellt Total_Menge_FERT_ABC bereits die Menge dar, wo der Wert aus WA_Menge_FERT bereits rausgerechnet wurde. Bei WA 0 passt es, sobald der Wert größer ist nicht.
- Müsste aus Zeile 62 (DATEID 20230821, WERKS 1010, MATNR 94074) nicht 7 rauskommen? Da Sobald die runtotal Summe der WA_Menge_FERT den Wert (Total_Menge_FERT_ABC) aus der Zeile überschreitet, darf diese nicht mehr mit in den Count laufen.

Nun wäre mein Lösungsansatz die Werte um eine Woche nach vorne zu schieben mittels eines weiteren Unions um dann die Lücke mit einer 0 zu füllen und den letzten Wert unten, würde ich dann entfernen? Denn den gesuchten Wert von ein zu reduzieren reicht hier nicht aus auch wenn das über eine CASE WHEN Formel das Problem löse, da es wiederum nicht immer aufgrund der WA_Menge_FERT ableitbar wäre.
 
@ukulele das hat ein wenig gedauert bevor ich zumindest ein wenig Verstanden haben was da passiert. Mir war nicht bewusst das etwas auf sich selbst in einem Subselect referenzieren kann. Das sorgt für ein ganz schönes Wirrwarr im Kopf.
Ja das ist defacto Rekursion aber ein sehr mächtiges Werkzeug und i.d.R. schneller als Schleifen oder Cursor aber eben auch theoretisch unendlich.
Noch scheinen dort aber drei größere Problem zu bestehen.
- Zum einen wird die MATNR 59025 in WERK 1044 komplett rausgefiltert, weil es dort keinen Rest von <=0 gibt.
Das habe ich gelöst. Irgendwie ist mir kein besserer Weg eingefallen als noch einen Zwischenschritt zu gehen. Ich Filtere das Ergebnis der Rekursion nicht mehr auf rest <= 0 sondern bringe es in eine Reihenfolge mit Partition. Von jeder Partition nehme ich dann nur den ersten Datensatz, der aber eigentlich dem letzten entspricht weil [count] DESC sortiert wird.
- Zum anderen stellt Total_Menge_FERT_ABC bereits die Menge dar, wo der Wert aus WA_Menge_FERT bereits rausgerechnet wurde. Bei WA 0 passt es, sobald der Wert größer ist nicht.
Okay wenn ich das richtig verstehe habe ich auch das gelöst in dem ich beim ersten Datensatz, also der Basis der Rekrusion, Total_Menge_FERT_ABC direkt als "Rest" betrachte. Dadurch ändern sich dann aber auch die Werte, in Post #20 bin ich z.B. von 3 Wochen für Datensatz 1 ausgegangen, das sind dann aber tatsächlich 4.

dateid Total_Menge_FERT_ABC WERKS MATNR WA_Menge_FERT running_total woche
----------- ------------------------ ----------- ----------- --------------------------------------- --------------------------------------- --------------------
20230626 23 1010 59025 11.000 11.000 1
20230703 133 1010 59025 10.000 21.000 2
20230710 124 1010 59025 9.000 30.000 3
20230717 115 1010 59025 9.000 39.000 4

20230626 Total_Menge_FERT_ABC = 23
Woche 1 -0 (weil WA_Menge_FERT in WA_Menge_FERT_ABC schon berücksichtigt) = 23
Woche 2 -10 = 13
Woche 3 -9 = 4
Woche 4 -9 = Bingo

- Müsste aus Zeile 62 (DATEID 20230821, WERKS 1010, MATNR 94074) nicht 7 rauskommen? Da Sobald die runtotal Summe der WA_Menge_FERT den Wert (Total_Menge_FERT_ABC) aus der Zeile überschreitet, darf diese nicht mehr mit in den Count laufen.
Nein ich denke nicht. Mit dem running_total habe ich jetzt gar nicht mehr verglichen, der passt z.B. alleine nicht weil er auch WA_Menge_FERT aus der ersten Woche mit berücksichtigt aber eventuell ist noch irgendwas falsch. Die konkreten Datensätze sind:

WERKS DateID MATNR Total_Menge_FERT_ABC WA_Menge_FERT
----------- ----------- ----------- -------------------- ---------------------------------------
1010 20230821 94074 0 0.000
1010 20230828 94074 0 0.000
1010 20230904 94074 0 0.000
1010 20230911 94074 0 0.000
1010 20230918 94074 3 0.000

20230821 Total_Menge_FERT_ABC = 0, das ist natürlich sofort erreicht. Kann sein das das an meinen Testdaten liegt.
Hier mein angepasster Code:
Code:
WITH t0 AS (
--t0 dient einzig und allein dazu aus DateID ein brauchbares Datum zu machen
SELECT    WERKS,
        DateID,
        dateadd(day,convert(INT,right(convert(CHAR(8),DateID),2))-1,
        dateadd(month,convert(INT,right(left(convert(CHAR(8),DateID),6),2))-1,
        dateadd(year,convert(INT,left(convert(CHAR(8),DateID),4))-1900,0)
        )) AS [Date],
        MATNR,
        cast(Total_Menge_FERT_ABC AS INT) AS Total_Menge_FERT_ABC,
        cast(WA_Menge_FERT AS INT) AS WA_Menge_FERT
FROM    tabelle
), t1 AS (
--Basis vom CTE
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        Total_Menge_FERT_ABC/* - WA_Menge_FERT*/ AS rest,
        1 AS [count]
FROM    t0
UNION ALL
--Rekursion vom CTE
SELECT    t1.DateID,
        t1.[Date],
        t1.Total_Menge_FERT_ABC,
        t1.WERKS,
        t1.MATNR,
        t1.WA_Menge_FERT,
        t1.rest - t0.WA_Menge_FERT AS rest,
        t1.[count] + 1 AS [count]
FROM    t1
INNER JOIN t0
ON        t1.WERKS = t0.WERKS
AND        t1.MATNR = t0.MATNR
AND        dateadd(day,t1.[count] * 7,t1.[Date]) = t0.[Date]
--der max(count) ist später interessant, also beim letzten Datensatz count = gesuchter Wert
WHERE    t1.rest > 0
--bei count = 99 dauert es dann 99 Wochen oder länger, hier wird eine Endlosrekursion verhindert und die Performance kann verbessert werden in dem Härtefälle nicht weiter durchgerechnet werden
AND        t1.[count] + 1 <= 99
), t2 AS (
SELECT    ROW_NUMBER() OVER (PARTITION BY WERKS, MATNR, [Date] ORDER BY [count] DESC) AS zeile,
        DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        rest,
        [count]
FROM    t1
)
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
--        rest,
        (CASE WHEN rest <= 0 THEN [count] ELSE NULL END) AS gesuchter_wert
FROM    t2
WHERE    zeile = 1
ORDER BY WERKS, MATNR, [Date], [count]
 
Guten Morgen,

ich muss das Thema leider noch einmal aufwärmen. Weil ich die Logik des Skripts noch nicht durchdringe. Bei Anwendung des obigen Skripts bekomme ich bei jeder zweiten Zeile ein falsches Ergebnis und ich verstehe nicht warum.
Unbenanntes Bild.png

Wert 1 in Lagerreichweite in KW, also die 11 stimmt, die 4 nicht, die 9 wiederum schon.

Könnt ihr hier noch einmal unterstützen?
 
Da bin ich jetzt natürlich geistig raus, zum Glück sind die Testdaten noch in dem dbfiddle Link. Testdaten + letzter Code
Code:
WITH tabelle(WERKS,DateID,MATNR,Total_Menge_FERT_ABC,WA_Menge_FERT) AS (
SELECT 1010,20230731,59025,99,8.000 UNION ALL SELECT
1010,20230807,59025,82,17.000 UNION ALL SELECT
1010,20230911,59025,16,12.000 UNION ALL SELECT
1010,20240603,59025,0,0.000 UNION ALL SELECT
1010,20240624,59025,0,0.000 UNION ALL SELECT
1044,20230703,59025,61,3.000 UNION ALL SELECT
1044,20230710,59025,58,3.000 UNION ALL SELECT
1044,20230814,59025,48,0.000 UNION ALL SELECT
1044,20230918,59025,43,2.000 UNION ALL SELECT
1044,20231009,59025,38,1.000 UNION ALL SELECT
1044,20231106,59025,33,1.000 UNION ALL SELECT
1044,20240122,59025,31,0.000 UNION ALL SELECT
1044,20240226,59025,31,0.000 UNION ALL SELECT
1044,20240311,59025,31,0.000 UNION ALL SELECT
1044,20240318,59025,31,0.000 UNION ALL SELECT
1044,20240401,59025,31,0.000 UNION ALL SELECT
1044,20240422,59025,31,0.000 UNION ALL SELECT
1044,20240527,59025,31,0.000 UNION ALL SELECT
1044,20240603,59025,31,0.000 UNION ALL SELECT
1044,20240610,59025,31,0.000 UNION ALL SELECT
1010,20230626,94074,1,0.000 UNION ALL SELECT
1010,20230717,94074,1,0.000 UNION ALL SELECT
1010,20230724,94074,1,0.000 UNION ALL SELECT
1010,20230807,94074,1,1.000 UNION ALL SELECT
1010,20230821,94074,0,0.000 UNION ALL SELECT
1010,20231211,94074,0,0.000 UNION ALL SELECT
1010,20240122,94074,0,0.000 UNION ALL SELECT
1010,20240408,94074,0,0.000 UNION ALL SELECT
1010,20240624,94074,0,0.000 UNION ALL SELECT
1010,20230814,59025,62,20.000 UNION ALL SELECT
1010,20231002,59025,0,11.000 UNION ALL SELECT
1010,20240108,59025,0,0.000 UNION ALL SELECT
1010,20240212,59025,0,0.000 UNION ALL SELECT
1010,20240318,59025,0,0.000 UNION ALL SELECT
1010,20240527,59025,0,0.000 UNION ALL SELECT
1010,20240617,59025,0,0.000 UNION ALL SELECT
1044,20230731,59025,48,4.000 UNION ALL SELECT
1044,20230904,59025,46,1.000 UNION ALL SELECT
1044,20231002,59025,39,2.000 UNION ALL SELECT
1044,20231113,59025,32,1.000 UNION ALL SELECT
1044,20231120,59025,32,0.000 UNION ALL SELECT
1044,20231204,59025,32,0.000 UNION ALL SELECT
1044,20240108,59025,31,0.000 UNION ALL SELECT
1044,20240115,59025,31,0.000 UNION ALL SELECT
1044,20240415,59025,31,0.000 UNION ALL SELECT
1044,20240506,59025,31,0.000 UNION ALL SELECT
1010,20231023,94074,0,0.000 UNION ALL SELECT
1010,20231113,94074,0,1.000 UNION ALL SELECT
1010,20231127,94074,0,1.000 UNION ALL SELECT
1010,20231204,94074,0,0.000 UNION ALL SELECT
1010,20240108,94074,0,0.000 UNION ALL SELECT
1010,20240129,94074,0,0.000 UNION ALL SELECT
1010,20240226,94074,0,0.000 UNION ALL SELECT
1010,20240401,94074,0,0.000 UNION ALL SELECT
1010,20240415,94074,0,0.000 UNION ALL SELECT
1010,20230626,59025,23,11.000 UNION ALL SELECT
1010,20230703,59025,133,10.000 UNION ALL SELECT
1010,20230710,59025,124,9.000 UNION ALL SELECT
1010,20230828,59025,44,19.000 UNION ALL SELECT
1010,20230925,59025,0,12.000 UNION ALL SELECT
1010,20231106,59025,0,6.000 UNION ALL SELECT
1010,20231113,59025,0,6.000 UNION ALL SELECT
1010,20231211,59025,0,4.000 UNION ALL SELECT
1010,20231225,59025,0,4.000 UNION ALL SELECT
1010,20240226,59025,0,0.000 UNION ALL SELECT
1010,20240325,59025,0,0.000 UNION ALL SELECT
1010,20240401,59025,0,0.000 UNION ALL SELECT
1010,20240415,59025,0,0.000 UNION ALL SELECT
1010,20240422,59025,0,0.000 UNION ALL SELECT
1044,20230626,59025,39,2.000 UNION ALL SELECT
1044,20230828,59025,47,1.000 UNION ALL SELECT
1044,20231023,59025,35,2.000 UNION ALL SELECT
1044,20231218,59025,32,0.000 UNION ALL SELECT
1044,20240212,59025,31,0.000 UNION ALL SELECT
1044,20240304,59025,31,0.000 UNION ALL SELECT
1010,20230710,94074,1,0.000 UNION ALL SELECT
1010,20230731,94074,1,0.000 UNION ALL SELECT
1010,20230828,94074,0,0.000 UNION ALL SELECT
1010,20231009,94074,1,1.000 UNION ALL SELECT
1010,20231016,94074,1,1.000 UNION ALL SELECT
1010,20240520,94074,0,0.000 UNION ALL SELECT
1010,20240603,94074,0,0.000 UNION ALL SELECT
1010,20230717,59025,115,9.000 UNION ALL SELECT
1010,20230821,59025,63,19.000 UNION ALL SELECT
1010,20230918,59025,3,13.000 UNION ALL SELECT
1010,20231016,59025,0,4.000 UNION ALL SELECT
1010,20231023,59025,0,5.000 UNION ALL SELECT
1010,20231030,59025,0,5.000 UNION ALL SELECT
1010,20231218,59025,0,3.000 UNION ALL SELECT
1010,20240115,59025,0,0.000 UNION ALL SELECT
1010,20240122,59025,0,0.000 UNION ALL SELECT
1010,20240408,59025,0,0.000 UNION ALL SELECT
1044,20230807,59025,48,0.000 UNION ALL SELECT
1044,20230821,59025,48,0.000 UNION ALL SELECT
1044,20230911,59025,45,1.000 UNION ALL SELECT
1044,20230925,59025,41,2.000 UNION ALL SELECT
1044,20231016,59025,37,1.000 UNION ALL SELECT
1044,20231030,59025,34,1.000 UNION ALL SELECT
1044,20231211,59025,32,0.000 UNION ALL SELECT
1044,20240101,59025,31,1.000 UNION ALL SELECT
1044,20240129,59025,31,0.000 UNION ALL SELECT
1010,20230703,94074,1,0.000 UNION ALL SELECT
1010,20230911,94074,0,0.000 UNION ALL SELECT
1010,20230918,94074,3,0.000 UNION ALL SELECT
1010,20230925,94074,0,0.000 UNION ALL SELECT
1010,20231002,94074,0,0.000 UNION ALL SELECT
1010,20231218,94074,0,0.000 UNION ALL SELECT
1010,20231225,94074,0,0.000 UNION ALL SELECT
1010,20240219,94074,0,0.000 UNION ALL SELECT
1010,20240304,94074,0,0.000 UNION ALL SELECT
1010,20240325,94074,0,0.000 UNION ALL SELECT
1010,20240429,94074,0,0.000 UNION ALL SELECT
1010,20231009,59025,0,4.000 UNION ALL SELECT
1010,20231120,59025,0,7.000 UNION ALL SELECT
1010,20231127,59025,0,6.000 UNION ALL SELECT
1010,20240129,59025,0,0.000 UNION ALL SELECT
1010,20240205,59025,0,0.000 UNION ALL SELECT
1010,20240219,59025,0,0.000 UNION ALL SELECT
1010,20240304,59025,0,0.000 UNION ALL SELECT
1010,20240429,59025,0,0.000 UNION ALL SELECT
1010,20240513,59025,0,0.000 UNION ALL SELECT
1044,20230717,59025,55,3.000 UNION ALL SELECT
1044,20231225,59025,32,0.000 UNION ALL SELECT
1044,20240205,59025,31,0.000 UNION ALL SELECT
1044,20240408,59025,31,0.000 UNION ALL SELECT
1010,20231030,94074,0,1.000 UNION ALL SELECT
1010,20231106,94074,0,0.000 UNION ALL SELECT
1010,20240101,94074,0,0.000 UNION ALL SELECT
1010,20240115,94074,0,0.000 UNION ALL SELECT
1010,20240311,94074,0,0.000 UNION ALL SELECT
1010,20240318,94074,0,0.000 UNION ALL SELECT
1010,20240506,94074,0,0.000 UNION ALL SELECT
1010,20240513,94074,0,0.000 UNION ALL SELECT
1010,20240527,94074,0,0.000 UNION ALL SELECT
1010,20240610,94074,0,0.000 UNION ALL SELECT
1010,20240617,94074,0,0.000 UNION ALL SELECT
1010,20230724,59025,107,8.000 UNION ALL SELECT
1010,20230904,59025,28,16.000 UNION ALL SELECT
1010,20231204,59025,0,5.000 UNION ALL SELECT
1010,20240101,59025,0,3.000 UNION ALL SELECT
1010,20240311,59025,0,0.000 UNION ALL SELECT
1010,20240506,59025,0,0.000 UNION ALL SELECT
1010,20240520,59025,0,0.000 UNION ALL SELECT
1010,20240610,59025,0,0.000 UNION ALL SELECT
1044,20230724,59025,52,3.000 UNION ALL SELECT
1044,20231127,59025,32,0.000 UNION ALL SELECT
1044,20240219,59025,31,0.000 UNION ALL SELECT
1044,20240325,59025,31,0.000 UNION ALL SELECT
1044,20240429,59025,31,0.000 UNION ALL SELECT
1044,20240513,59025,31,0.000 UNION ALL SELECT
1044,20240520,59025,31,0.000 UNION ALL SELECT
1044,20240617,59025,31,0.000 UNION ALL SELECT
1044,20240624,59025,31,0.000 UNION ALL SELECT
1010,20230814,94074,0,0.000 UNION ALL SELECT
1010,20230904,94074,0,0.000 UNION ALL SELECT
1010,20231120,94074,0,0.000 UNION ALL SELECT
1010,20240205,94074,0,0.000 UNION ALL SELECT
1010,20240212,94074,0,0.000 UNION ALL SELECT
1010,20240422,94074,0,0.000
), t0 AS (
--t0 dient einzig und allein dazu aus DateID ein brauchbares Datum zu machen
SELECT    WERKS,
        DateID,
        dateadd(day,convert(INT,right(convert(CHAR(8),DateID),2))-1,
        dateadd(month,convert(INT,right(left(convert(CHAR(8),DateID),6),2))-1,
        dateadd(year,convert(INT,left(convert(CHAR(8),DateID),4))-1900,0)
        )) AS [Date],
        MATNR,
        cast(Total_Menge_FERT_ABC AS INT) AS Total_Menge_FERT_ABC,
        cast(WA_Menge_FERT AS INT) AS WA_Menge_FERT
FROM    tabelle
), t1 AS (
--Basis vom CTE
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        Total_Menge_FERT_ABC/* - WA_Menge_FERT*/ AS rest,
        1 AS [count]
FROM    t0
UNION ALL
--Rekursion vom CTE
SELECT    t1.DateID,
        t1.[Date],
        t1.Total_Menge_FERT_ABC,
        t1.WERKS,
        t1.MATNR,
        t1.WA_Menge_FERT,
        t1.rest - t0.WA_Menge_FERT AS rest,
        t1.[count] + 1 AS [count]
FROM    t1
INNER JOIN t0
ON        t1.WERKS = t0.WERKS
AND        t1.MATNR = t0.MATNR
AND        dateadd(day,t1.[count] * 7,t1.[Date]) = t0.[Date]
--der max(count) ist später interessant, also beim letzten Datensatz count = gesuchter Wert
WHERE    t1.rest > 0
--bei count = 99 dauert es dann 99 Wochen oder länger, hier wird eine Endlosrekursion verhindert und die Performance kann verbessert werden in dem Härtefälle nicht weiter durchgerechnet werden
AND        t1.[count] + 1 <= 99
), t2 AS (
SELECT    ROW_NUMBER() OVER (PARTITION BY WERKS, MATNR, [Date] ORDER BY [count] DESC) AS zeile,
        DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        rest,
        [count]
FROM    t1
)
SELECT    DateID,
        [Date],
        Total_Menge_FERT_ABC,
        WERKS,
        MATNR,
        WA_Menge_FERT,
        rest,
        (CASE WHEN rest <= 0 THEN [count] ELSE NULL END) AS gesuchter_wert
FROM    t2
WHERE    zeile = 1
ORDER BY WERKS, MATNR, [Date], [count]
Du hast jetzt neue Daten gepostet. Daher bitte entweder einmal die neuen Daten zum testen bereit stellen oder den Fehler in den alten Daten zeigen. Vor allem, was wäre denn der richtige Wert?
 
Hier noch die ersten Zeilen vom Ergebnis, bitte da mal den Fehler aufzeigen:
DateID Date Total_Menge_FERT_ABC WERKS MATNR WA_Menge_FERT rest gesuchter_wert
----------- ----------------------- -------------------- ----------- ----------- ------------- ----------- --------------
20230626 2023-06-26 00:00:00.000 23 1010 59025 11 -5 4
20230703 2023-07-03 00:00:00.000 133 1010 59025 10 -4 11
20230710 2023-07-10 00:00:00.000 124 1010 59025 9 -4 10
20230717 2023-07-17 00:00:00.000 115 1010 59025 9 -4 9
20230724 2023-07-24 00:00:00.000 107 1010 59025 8 -4 8
20230731 2023-07-31 00:00:00.000 99 1010 59025 8 -4 7
20230807 2023-08-07 00:00:00.000 82 1010 59025 17 -4 6
20230814 2023-08-14 00:00:00.000 62 1010 59025 20 -4 5
20230821 2023-08-21 00:00:00.000 63 1010 59025 19 -9 6
20230828 2023-08-28 00:00:00.000 44 1010 59025 19 -9 5
20230904 2023-09-04 00:00:00.000 28 1010 59025 16 -9 4
20230911 2023-09-11 00:00:00.000 16 1010 59025 12 -9 3
20230918 2023-09-18 00:00:00.000 3 1010 59025 13 -9 2
20230925 2023-09-25 00:00:00.000 0 1010 59025 12 0 1
20231002 2023-10-02 00:00:00.000 0 1010 59025 11 0 1
20231009 2023-10-09 00:00:00.000 0 1010 59025 4 0 1
20231016 2023-10-16 00:00:00.000 0 1010 59025 4 0 1
20231023 2023-10-23 00:00:00.000 0 1010 59025 5 0 1
20231030 2023-10-30 00:00:00.000 0 1010 59025 5 0 1
20231106 2023-11-06 00:00:00.000 0 1010 59025 6 0 1
20231113 2023-11-13 00:00:00.000 0 1010 59025 6 0 1
...
 
Werbung:
Zurück
Oben