Daten-Auffüllung mittels Schleife

Romero

Fleissiger Benutzer
Beiträge
51
Hallo zusammen,

bisher habe ich nachstehendes Problem bisher nur per Schleife z.B. im VBA lösen können.
Doch nun bräuchte ich eine Lösung via SQL.

Folgende Problematik habe ich:

Mittels Datenbank-Abfrage erhalte ich nachstehende Ausgangstabelle:
BestellnummerBestellpositionMaterial-IDDatumMengeKomp.-IDKomp.-MengeGes.-MengeLagerbestandneuer Lagerb.
70001454591001234567827.05.20251123456781143
70001454592002345678927.05.20251123456781142
70001454593003456789027.05.2025112345678334-1
70001454594004567890127.05.2025112345678664-7
70001454595005678901227.05.2025312345678264-13
70001454596006789012327.05.2025212345678244-17
70001454597007890123427.05.2025112345678114-18
70001454598008901234527.05.2025112345678114-19
70001454599009012345627.05.2025112345678224-21
700014545910000123456727.05.2025112345678114-22
Die Tabelle ist nach den Kriterien Datum, Bestellnummer, Bestellposition, Komp.-ID sortiert. Die Gesamt-Menge (Ges.-Menge) ergibt sich aus der Spalte Menge x Komp.-Menge und ist die auszuwertende Menge.
Anmerkung: zu einer Mat-ID können noch weitere Komp.-IDs untergeordnet sein.

Grundlegend soll (gemäß der obigen Tabelle) im ersten Schritt die Gesamt-Menge von dem Lagerbestand abgezogen und als "neuer Lagerbestand" angezeigt werden.
Das habe ich mittels SUM(...) OVER (PARTITION BY ... ORDER BY ...) umgesetzt.

Nun folgt aber der nächste Part, welcher ich bisher nur per Schleife lösen konnte.
Zu jeder Komp.-ID werden immer wieder Aufträge erstellt/ausgelöst, welche in die obige Tabelle mit einfließen müssen.
Diese Auftrags-Tabelle sähe so aus:
AuftragsnummerMaterial-IDVorgangsposition
8123456712345678500
8234567812345678400
8345678912345678300
8456789012345678100
8567890112345678NULL
Diese Tabelle wurde sortiert nach Vorgangsposition (je höher die Zahl, desto fortgeschrittener ist der Auftrag), danach nach der Auftragsnummer (Nummer ist fortlaufend).

Am Ende müsste die obige Basis-Tabelle mit der unteren Auftragstabelle so gejoined werden, damit nachstehende neue Tabelle entsteht:
Material-IDKomp.-IDGes.-MengeStatusneuer Lagerb.AuftragsnummerVorgangspos.
12345678123456781aus Lager3
23456789123456781aus Lager2
34567890123456781aus Lager1
34567890123456781aus Lager0
34567890123456781aus Auftrag-181234567500
45678901123456781aus Auftrag-282345678400
45678901123456781aus Auftrag-383456789300
45678901123456781aus Auftrag-484567890100
45678901123456781aus Auftrag-585678901NULL
45678901123456781fehlt-6
45678901123456781fehlt-7
56789012123456781fehlt-8
...............

Nun die Frage: ist das so mittels SQL auflösbar? Wenn ja, wie?

Wichtig sei: zuerst immer aus dem Lager, bis Lager leer ist. Dann soll geprüft werden, ob Aufträge vorhanden sind bzw. diese aufgelistet werden (sortiert), und die restlichen Positionen einfach mit Status leer beschreiben.

Vielen Dank schon mal im Voraus...

LG Romero
 
Werbung:
Also ich bin mir erstmal sicher, dass das lösbar ist. Ich bin mir nur noch nicht ganz sicher, wie sich das elegant umsetzen lässt und ob ich das komplett verstehe.

Also du hast eine Komponente 12345678 und Aufträge, die diese "verbrauchen". Dein Lager ist leer und im Anschluss hast du eine Auftrags-Tabelle, wo für diese Komponente wieder ein Zulauf geplant ist? Soweit richtig?

Fragen:

1) Deine Auftragstabelle / Zulauf, gibt es da auch ein Datum? Was, wenn mehrere Vorgangspositionen den selben "Fortschrittsstatus" haben?
2) Du hast ja bereits mit OVER() die erste Tabelle ermittelt. Das cleverste wäre es vermutlich, beides zu kombinieren. Vielleicht kannst du den Code und die Ausgangstabellen für deinen ersten Schritt, vielleicht vereinfacht, mal posten.

Meine erste Überlegung wäre etwa so: Ich tue so, als wäre der Zulauf bereits im Lager und hänge das mit UNION ALL an die Lagertabelle an. Dann ordne ich den Zulauf hinter die Positionen im Lager und mache das gleiche mit OVER(), so das erst der Lagerbestand, im Anschluss der Zulauf abgezogen wird und zum Schluss das ganze ins Negative läuft. Mit CASE kann man dann das Ergebnis kosmetisch behandeln, z.B. keine negativen Werte und eventuell eine erste Spalte Lager und eine zweite Spalte Zulauf ausgeben, wie man mag.
 
Hey ukulele,

vielen Dank für deine schnelle Antwort ;)

Hier meine Antworten:
Also du hast eine Komponente 12345678 und Aufträge, die diese "verbrauchen". Dein Lager ist leer und im Anschluss hast du eine Auftrags-Tabelle, wo für diese Komponente wieder ein Zulauf geplant ist? Soweit richtig?
Ja genau. Die Komponenten "befüttern" die vorher-genannte Material-ID. Diese Befütterung kann entweder über das Lager erfolgen (vorrangig) oder halt über den Zulauf mittels Auftrag erfolgen.

1) Deine Auftragstabelle / Zulauf, gibt es da auch ein Datum? Was, wenn mehrere Vorgangspositionen den selben "Fortschrittsstatus" haben?
Ja dazu gibt es ein Datum, eigentlich ist das Datum für die Zuordnung zu der Komponente nicht so relevant. Dennoch könnte man es noch hinzufügen um zu sagen, "wenn der Fortschrittstatus gleich ist, nimm den ältesten Auftrag".

2) Du hast ja bereits mit OVER() die erste Tabelle ermittelt. Das cleverste wäre es vermutlich, beides zu kombinieren. Vielleicht kannst du den Code und die Ausgangstabellen für deinen ersten Schritt, vielleicht vereinfacht, mal posten.
Hier mein Code:
SQL:
WITH    Bestellung AS
        (
            SELECT
                    B.[EBELN] AS [EBELN],
                    B.[EBELP] AS [EBELP],
                    B.[METNR] AS [MATNR],
                    CONVERT(date, B.[EINDT]) AS [EINDT],
                    B.[MENGE] AS [MENGE]

            FROM    [SAP].[dbo].[Bestellung] AS B                                                LEFT JOIN
                    [SAP].[dbo].[Lieferung] AS L            ON L.[VGBEL] = B.[EBELN]
                                                            AND L.[VGPOS] = B.[EBELP]            LEFT JOIN
                    [SAP].[dbo].[Stammdaten] AS SD            ON SD.[MATNR] = B.[METNR]

            WHERE    --1=1
                    ISNULL(L.[VGBEL], '---') = '---'
                    AND B.[LOEKZ] <> 'L'
                    AND SD.[DISPO] = 'Y78'
                    AND CONVERT(date, B.[EINDT]) <= '2025-06-01'
        ),
        Stuecklisten_Aufloesung__Stepp1 AS
        (
            SELECT
                    DISTINCT
                    B.[MATNR],
                    STL.[KOMPONENTE_MATNR],
                    SD.[DISPO],
                    STL.[KOMPONENTENMENGE]

            FROM    Bestellung AS B                                                                            LEFT JOIN
                    [SAP].[dbo].[Stueckliste] AS STL            ON STL.[MATNR] = B.[MATNR]                    LEFT JOIN
                    [SAP].[dbo].[Stammdaten] AS SD                ON SD.[MATNR] = STL.[KOMPONENTE_MATNR]

            WHERE    STL.[BESCHAFFUNGSKENNZEICHEN] = 'E'
                    AND (SD.[DISPO] = 'Y78' OR SD.[DISPO] = 'Y79')
        ),
        Stuecklisten_Aufloesung__Stepp2 AS
        (
            SELECT
                    STL_A.[MATNR] AS [MATNR],
                    STL.[KOMPONENTE_MATNR],
                    SD.[DISPO],
                    STL.[KOMPONENTENMENGE]

            FROM    Stuecklisten_Aufloesung__Stepp1 AS STL_A                                                    LEFT JOIN
                    [SAP].[dbo].[Stueckliste] AS STL            ON STL.[MATNR] = STL_A.[KOMPONENTE_MATNR]        LEFT JOIN
                    [SAP].[dbo].[Stammdaten] AS SD                ON SD.[MATNR] = STL.[KOMPONENTE_MATNR]

            WHERE    STL_A.[DISPO] = 'Y78'
                    AND STL.[BESCHAFFUNGSKENNZEICHEN] = 'E'
                    AND (SD.[DISPO] = 'Y78' OR SD.[DISPO] = 'Y79')
        ),
        Stueckliste AS
        (
            SELECT * FROM Stuecklisten_Aufloesung__Stepp1 WHERE DISPO <> 'Y78'
            UNION
            SELECT * FROM Stuecklisten_Aufloesung__Stepp2
        ),
        Komponenten AS
        (
            SELECT
                    Bestellung.*,
                    STL.[KOMPONENTE_MATNR],
                    STL.[DISPO],
                    STL.[KOMPONENTENMENGE],
                    Bestellung.[MENGE] * STL.[KOMPONENTENMENGE] AS [GESME],
                    (SELECT SUM(LG.[GESME]) FROM [SAP].[dbo].[Lagerspiegel] AS LG WHERE LG.[MATNR] = STL.[KOMPONENTE_MATNR]) AS Lagerbestand,
                    (SELECT SUM(AD_K.[GAMNG]) FROM [SAP].[dbo].[Auftragsdaten__Kopf] AS AD_K WHERE AD_K.[MATNR] = STL.[KOMPONENTE_MATNR] AND AD_K.[Status_Anwender] NOT LIKE '%AUSS%' AND (AD_K.[Status_System] NOT LIKE '%GLFT%' AND 
                            AD_K.[Status_System] NOT LIKE '%ABGS%' AND AD_K.[Status_System] NOT LIKE '%LÖVM%' AND AD_K.[Status_System] NOT LIKE '%LÖKZ%' AND AD_K.[Status_System] NOT LIKE '%TABG%')) AS [WKO_in_Fertigung]

            FROM    Bestellung AS B                                                        LEFT JOIN
                    Stueckliste AS STL                    ON STL.[MATNR] = B.[MATNR]
        )

SELECT    *,
        SUM(([GESME] * -1)) OVER (PARTITION BY [KOMPONENTE_MATNR] ORDER BY [EINDT], [EBELN], [EBELP], [KOMPONENTE_MATNR]) AS [neuer Lagerbestand]
FROM    Komponenten
WHERE    KOMPONENTE_MATNR = '54662872' --or KOMPONENTE_MATNR = '54663084'
ORDER BY EINDT, EBELN, EBELP, KOMPONENTE_MATNR
GO

Meine erste Überlegung wäre etwa so: Ich tue so, als wäre der Zulauf bereits im Lager und hänge das mit UNION ALL an die Lagertabelle an. Dann ordne ich den Zulauf hinter die Positionen im Lager und mache das gleiche mit OVER(), so das erst der Lagerbestand, im Anschluss der Zulauf abgezogen wird und zum Schluss das ganze ins Negative läuft. Mit CASE kann man dann das Ergebnis kosmetisch behandeln, z.B. keine negativen Werte und eventuell eine erste Spalte Lager und eine zweite Spalte Zulauf ausgeben, wie man mag.
Hier bin ich n bissl überfragt: kannst du das mal Code-elarisch darstellen?

Aktuell probiere ich das mittels einer WHILE-Schleife aus, was grundlegend im Versuch positiv verlief.
Aber hier las ich, dass man im SQL eigentlich keine Schleifen verwenden sollte...

LG Romero
 
Ja da werde ich mich mal dran versuchen, das kostet allerdings ein wenig Zeit die ich erst später habe. Ich hoffe, ich denke heute Abend wieder dran :)
 
Einige Sachen in deinem Code gefallen mir nicht bzw. ich verstehe nicht alles. Daher habe ich den erstmal zerlegt:

1) Stückliste

An dieser Stelle habe ich etwas grundlegend verändert. Deine Stücklistenauflösung arbeitet genau zwei Ebenen ab, vermutlich hast du nicht mehr. Das kann man so machen, ist aber nicht erweiterbar. Daher habe ich eine Rekursion eingebaut, wie man das normalerweise bei Stücklisten so macht, und was wirklich sehr gut mit SQL geht (zu erkennen an dem Verweis auf Stueckliste_Auflösung innerhalb der Definition von Stueckliste_Auflösung).

Deine 2te Ebene der Stückliste berücksichtigt nicht die Menge aus der ersten Ebene. Ich bin mir nicht sicher, wie das in deinen Daten funktioniert. Normalerweise würde ich sagen Menge Ebene 1 * Menge Ebene 2 aber das kann ich nur annehmen, siehe Stueckliste_Auflösung.[KOMPONENTENMENGE] * [Stueckliste].[KOMPONENTENMENGE].

Ich habe deine LEFT JOINs gegen INNER JOINs getauscht, da sie, zusammen mit den WHERE-Bedingungen, defacto INNER JOINs sind. Auch habe ich die Bedingungen aus der WHERE-Condition in die Join-Condition gezogen, das mag nicht Jeder, ich aber. Inhaltlich sollte es auf das gleiche Ergebnis hinauslaufen, vermutlich auch in der Performance.

In deinem ursprünglichen Code war noch ein DISTINCT, das mich ein wenig stutzig macht. An der Stelle sollte das eigentlich nicht nötig sein, sonst hast du eventuell zu wenig Teile in deinem Ergebnis?
Code:
        WITH Stueckliste_Auflösung AS
        (
        SELECT    1 AS Ebene,
                [Stueckliste].[MATNR] AS Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                [Stueckliste].[KOMPONENTENMENGE]
        FROM    [SAP].[dbo].[Stueckliste]
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        STL.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    [BESCHAFFUNGSKENNZEICHEN] = 'E'
        UNION ALL
        SELECT    Stueckliste_Auflösung.Ebene + 1,
                Stueckliste_Auflösung.Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                Stueckliste_Auflösung.[KOMPONENTENMENGE] * [Stueckliste].[KOMPONENTENMENGE]
        FROM    Stueckliste_Auflösung
        INNER JOIN [SAP].[dbo].[Stueckliste]
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = [Stueckliste].[MATNR]
        AND        [Stueckliste].[BESCHAFFUNGSKENNZEICHEN] = 'E'
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    Stueckliste_Auflösung.Ebene + 1 <= 2
        )
SELECT * FROM Stueckliste_Auflösung
Stueckliste_Auflösung sollte bis hier hin genau das liefern, was "Stueckliste" in deinem Code bereit stellt. Allein die Einschränkung DISPO <> 'Y78' fehlt irgendwie noch, wobei ich die nicht ganz verstehe. Eventuell muss da noch was angepasst werden. Bitte teste das mal, damit wir die selbe Teileliste als Ausgangspunkt haben.

BTW: Es scheint mir nicht so klug, "Stueckliste" als Alias zu verwenden wenn es auch eine Tabelle mit dem Namen gibt. Ich habe jetzt auf die schnelle Stueckliste_Auflösung genommen, Aliase und Formatierung kann man ja später noch nach Geschmack anpassen.

2) Komponenten AS

Ich habe eine weile gebraucht um zu verstehen, was genau hier passiert und passieren soll. Im Prinzip brauchst du SUM(LG.[GESME]) FROM [SAP].[dbo].[Lagerspiegel] als Anfangsbestand pro STL.[KOMPONENTE_MATNR], tatsächlich arbeitest du aber etwas ungeschickt mit Subselects. Pro Ergebniszeile wird dabei ein eigener Select auf die Lagertabelle ausgeführt. Das machst du in einer eigenen Abfrage, die du dann später mit Windows-Funktionen (OVER) durchläufst. Ich würde das eher in einen Schritt legen, das ist performanter und logischer.

Vor allem stört mich hier aber die Tatsache, das der zweite Subselect auf ganz andere Daten zugreift ([SAP].[dbo].[Auftragsdaten__Kopf]). Die Spalte Komponenten.[WKO_in_Fertigung] scheint nicht in dem Ergebnis aus deinem Post #1 zu sein und für den Sachverhalt überhaupt nicht relevant?

BTW: Für den Alias "Bestellung" wird gleich wieder ein neuer Alias "B" vergeben. Du musst übrigens, zumindest im Management Studio, keinen Alias vergeben :-) Im Select-Teil steht hier aber auch wieder nicht "B", verwirrend...

Ich habe das mal umgestellt mit dem Ziel, erstmal dein Ergebnis aus der ersten Tabelle in Post #1 zu reproduzieren aber etwas effektiver:
Code:
WITH    Bestellung AS
        (
            SELECT
                    B.[EBELN] AS [EBELN],
                    B.[EBELP] AS [EBELP],
                    B.[METNR] AS [MATNR],
                    CONVERT(date, B.[EINDT]) AS [EINDT],
                    B.[MENGE] AS [MENGE]

            FROM    [SAP].[dbo].[Bestellung] AS B
            LEFT JOIN [SAP].[dbo].[Lieferung] AS L            ON L.[VGBEL] = B.[EBELN]
                                                            AND L.[VGPOS] = B.[EBELP]
            LEFT JOIN [SAP].[dbo].[Stammdaten] AS SD            ON SD.[MATNR] = B.[METNR]

            WHERE   ISNULL(L.[VGBEL], '---') = '---'
                    AND B.[LOEKZ] <> 'L'
                    AND SD.[DISPO] = 'Y78'
                    AND CONVERT(date, B.[EINDT]) <= '2025-06-01'
        ),
        Stueckliste_Auflösung AS
        (
        SELECT    1 AS Ebene,
                [Stueckliste].[MATNR] AS Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                [Stueckliste].[KOMPONENTENMENGE]
        FROM    [SAP].[dbo].[Stueckliste]
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        STL.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    [BESCHAFFUNGSKENNZEICHEN] = 'E'
        UNION ALL
        SELECT    Stueckliste_Auflösung.Ebene + 1,
                Stueckliste_Auflösung.Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                Stueckliste_Auflösung.[KOMPONENTENMENGE] * [Stueckliste].[KOMPONENTENMENGE]
        FROM    Stueckliste_Auflösung
        INNER JOIN [SAP].[dbo].[Stueckliste]
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = [Stueckliste].[MATNR]
        AND        [Stueckliste].[BESCHAFFUNGSKENNZEICHEN] = 'E'
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    Stueckliste_Auflösung.Ebene + 1 <= 2
        ),
        LG AS
        (
        SELECT    [MATNR],
                SUM([GESME]) AS [LGESME]
        FROM    [SAP].[dbo].[Lagerspiegel]
        GROUP BY [MATNR]
        )
SELECT    Bestellung.*,
        STLA.[KOMPONENTE_MATNR],
        STLA.[DISPO],
        STLA.[KOMPONENTENMENGE],
        Bestellung.[MENGE] * STL.[KOMPONENTENMENGE] AS [GESME],
        LG.[LGESME] AS Lagerbestand,
        ISNULL(LG.[LGESME],0) -
        SUM(Bestellung.[MENGE] * STL.[KOMPONENTENMENGE]) OVER (PARTITION BY [KOMPONENTE_MATNR] ORDER BY Bestellung.EINDT, Bestellung.EBELN, Bestellung.EBELP, Bestellung.KOMPONENTE_MATNR) AS [neuer Lagerbestand]
FROM    Bestellung
INNER JOIN Stueckliste_Auflösung AS STLA
ON        Bestellung.[MATNR] = STLA.[MATNR]
AND        STLA.[DISPO] <> 'Y78' --nicht sicher
LEFT JOIN LG
ON        STLA.[KOMPONENTE_MATNR] = LG.[MATNR]
WHERE    Bestellung.KOMPONENTE_MATNR = '54662872' --OR Bestellung.KOMPONENTE_MATNR = '54663084'
ORDER BY Bestellung.EINDT, Bestellung.EBELN, Bestellung.EBELP, Bestellung.KOMPONENTE_MATNR
GO

3) Berücksichtigung Zulauf

Das würde ich dann angehen, wenn der Code oben das richtige Ergebnis liefert. Ich habe leider keine Testdaten, aber ich glaube, du kriegst das eventuell zum Laufen und findest alle Fehler. Gerne kannst du auch Format und Aliase anpassen, aber bitte keine Alias doppelt verwenden.
 
3) Berücksichtigung Zulauf

sähe dann irgendwie so aus:
Code:
WITH    Bewegungen AS
        (
            SELECT    'B' AS Typ, --Bestellung durch Abnehmer
                    B.[EBELN] AS [EBELN],
                    B.[EBELP] AS [EBELP],
                    B.[METNR] AS [MATNR],
                    CONVERT(date, B.[EINDT]) AS [EINDT],
                    B.[MENGE] AS [MENGE],
                    NULL AS Auftragsnummer,
                    NULL AS Vorgangsposition

            FROM    [SAP].[dbo].[Bestellung] AS B
            LEFT JOIN [SAP].[dbo].[Lieferung] AS L            ON L.[VGBEL] = B.[EBELN]
                                                            AND L.[VGPOS] = B.[EBELP]
            LEFT JOIN [SAP].[dbo].[Stammdaten] AS SD            ON SD.[MATNR] = B.[METNR]

            WHERE   ISNULL(L.[VGBEL], '---') = '---'
                    AND B.[LOEKZ] <> 'L'
                    AND SD.[DISPO] = 'Y78'
                    AND CONVERT(date, B.[EINDT]) <= '2025-06-01'

            UNION ALL
            SELECT    'A', --Auftrag für Zulauf
                    NULL,
                    NULL,
                    [Auftrags-Tabelle].[Material-ID],
                    [Auftrags-Tabelle].Datum,
                    [Auftrags-Tabelle].Menge,
                    [Auftrags-Tabelle].Auftragsnummer,
                    [Auftrags-Tabelle].Vorgangsposition
            FROM    [Auftrags-Tabelle]
        ),
        Stueckliste_Auflösung AS
        (
        SELECT    1 AS Ebene,
                [Stueckliste].[MATNR] AS Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                [Stueckliste].[KOMPONENTENMENGE]
        FROM    [SAP].[dbo].[Stueckliste]
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        STL.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    [BESCHAFFUNGSKENNZEICHEN] = 'E'
        UNION ALL
        SELECT    Stueckliste_Auflösung.Ebene + 1,
                Stueckliste_Auflösung.Stueckliste_MATNR,
                [Stueckliste].[MATNR],
                [Stueckliste].[KOMPONENTE_MATNR],
                SD.[DISPO],
                Stueckliste_Auflösung.[KOMPONENTENMENGE] * [Stueckliste].[KOMPONENTENMENGE]
        FROM    Stueckliste_Auflösung
        INNER JOIN [SAP].[dbo].[Stueckliste]
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = [Stueckliste].[MATNR]
        AND        [Stueckliste].[BESCHAFFUNGSKENNZEICHEN] = 'E'
        INNER JOIN [SAP].[dbo].[Stammdaten] AS SD
        ON        Stueckliste_Auflösung.[KOMPONENTE_MATNR] = SD.[MATNR]
        AND        SD.[DISPO] IN ( 'Y78','Y79' )
        WHERE    Stueckliste_Auflösung.Ebene + 1 <= 2
        ),
        LG AS
        (
        SELECT    [MATNR],
                SUM([GESME]) AS [LGESME]
        FROM    [SAP].[dbo].[Lagerspiegel]
        GROUP BY [MATNR]
        ),
        t AS
        (
        SELECT    Bewegungen.*,
                STLA.[KOMPONENTE_MATNR],
                STLA.[DISPO],
                STLA.[KOMPONENTENMENGE],
                Bewegungen.[MENGE] * STL.[KOMPONENTENMENGE] AS [GESME],
                isnull(LG.[LGESME],0) AS Lagerbestand,
                (    CASE
                    WHEN    Bewegungen.Typ = 'B'
                    THEN    SUM(Bewegungen.[MENGE] * STL.[KOMPONENTENMENGE]) OVER (PARTITION BY Bewegungen.[MATNR] ORDER BY Bewegung.Typ DESC, isnull(Bewegungen.Vorgangsposition,0) DESC, Bewegungen.EINDT, Bewegungen.EBELN, Bewegungen.EBELP, Bewegungen.KOMPONENTE_MATNR)
                    ELSE    0
                    END ) AS Veränderung_durch_B,
                (    CASE
                    WHEN    Bewegungen.Typ = 'A'
                    THEN    SUM(Bewegungen.[MENGE] * STL.[KOMPONENTENMENGE]) OVER (PARTITION BY Bewegungen.[MATNR] ORDER BY Bewegung.Typ DESC, isnull(Bewegungen.Vorgangsposition,0) DESC, Bewegungen.EINDT, Bewegungen.EBELN, Bewegungen.EBELP, Bewegungen.KOMPONENTE_MATNR)
                    ELSE    0
                    END ) AS Veränderung_durch_A
        FROM    Bewegungen
        INNER JOIN Stueckliste_Auflösung AS STLA
        ON        Bewegungen.[MATNR] = STLA.[MATNR]
        AND        STLA.[DISPO] <> 'Y78' --nicht sicher
        LEFT JOIN LG
        ON        STLA.[KOMPONENTE_MATNR] = LG.[MATNR]
        WHERE    Bewegungen.KOMPONENTE_MATNR = '54662872' --OR Bewegungen.KOMPONENTE_MATNR = '54663084'
        )
SELECT    t.*,
        (    CASE
            WHEN    t.Lagerbestand - t.Veränderung_durch_B <= 0
            THEN    0
            ELSE    t.Lagerbestand - t.Veränderung_durch_B
            END ) AS neuer_Lagerbestand,
        (    CASE
            WHEN    t.Lagerbestand - t.Veränderung_durch_B > 0
            THEN    t.Veränderung_durch_A
            WHEN    t.Lagerbestand - t.Veränderung_durch_B <= 0
            AND        t.Lagerbestand - t.Veränderung_durch_B + t.Veränderung_durch_A >= 0
            THEN    t.Lagerbestand - t.Veränderung_durch_B + t.Veränderung_durch_A
            ELSE    0
            END ) AS Puffer_durch_Zulauf_Auftrag,
        (    CASE
            WHEN    t.Lagerbestand - t.Veränderung_durch_B + t.Veränderung_durch_A < 0
            THEN    abs(t.Lagerbestand - t.Veränderung_durch_B + t.Veränderung_durch_A)
            ELSE    0
            END ) AS fehlt
FROM    t
ORDER BY t.EINDT, t.EBELN, t.EBELP, t.KOMPONENTE_MATNR
GO
Das ist jetzt ein ziemliches Chaos mit den ganzen Aliasen. Am Besten, du strukturierst das noch einmal schön sobald es läuft.

Au0erdem werden hier mit sum() OVER an mehreren Stellen Zahlen aufaddiert. Ich weiß nicht, wie hoch das gehen kann, nicht, das irgendwo ein Integer überlaufen kann.
 
Ich hab da halt Spaß dran, verklag mich doch :)

Aber: Ich habe nichts davon getestet, weil ich zu faul war, mir aus dem Ergebnis in Post #1 Testdatensätze zu stricken. Daher war ich an vielen Stellen nicht sicher, das würde ich bei Problemen noch nachholen. Allerdings müsste sich der OP erstmal zurückmelden.
 
verklag mich doch :)
Nene, das sollte einfach ein Kompliment sein. Vielleicht registriert ja auch @Romero, was er da geschenkt bekommt.
Aber: Ich habe nichts davon getestet, weil ich zu faul war, mir aus dem Ergebnis in Post #1 Testdatensätze zu stricken
Das würde ich so nicht sagen, diesen Job kann jeder TE gut selbst erledigen, wenn er auch nur ansatzweise so ein Feedback wie von Dir (ohne Testdatensätze) erwartet.
 
Anfangs hat @Romero gut geliefert, ich habe schon sehr viel weniger Informationen mit sehr viel wirreren Anfragen gesehen. Ich denke mal, er könnte das aktuell zum Laufen kriegen, eventuell ist aber irgendwo noch ein Denkfehler drin wer weiß.
 
Hallo ukulele, Hallo an den Rest,

sorry das ich mich jetzt erst melde, aber ich hatte mir mal ne kleine arbeitliche Auszeit gegönnt.
Nun binsch mal wieder uff Arbeit und habe deinen Code genüsslich aufgenommen, getestet und erfreue mich an dem Resultat, welches mir liefert, was ich möchte.
Ukulele, ich danke dir zu tiefst mich verneig

@dabadepdu du hast Recht, so eine Ausführlichkeit, wie sie @ukulele präsentiert hat, ist wahrlich fast kaum in Worte zu fassen. Daher spreche ich auch einen Riesen-Dank aus für seine Arbeit...

Ich hab den obigen Code in meine SQL-Umgebung eingebunden, für meine Übersichtlichkeit entsprechend formatiert und angepasst.

Was mich am meisten faszinierte, ist diese rekursive aufgelöste Stückliste. Kannte ich so in dieser Form noch nicht bzw. hatte ich ja, wie oben dargestellt, anders umgesetzt...

@ukulele 😘😉
 
Schön, das es läuft. Ich konnte mir vor allem auf SD.[DISPO] IN ( 'Y78','Y79' ) nicht so richtig einen Reim darauf machen, wann was der Fall ist.

Rekursion ist ein sehr mächtiges Werkzeug und sehr flott. Man muss nur immer im Blick haben wie weit man das treibt bzw. irgendwann knallt es. In diesem Fall geht das eigentlich nicht weil mit WHERE Stueckliste_Auflösung.Ebene + 1 = 2 ist ja die maximale tiefe begrenzt. Bei Bedarf kann das aber deutlich tiefer gehen :)

An deiner Formatierung würde ich normalerweise nichts aussetzen, jedem das seine. Allerdings hat mich die Platzierung der JOIN-Schlüsselwörter doch sehr, äh, frustriert :)
 
Werbung:
An deiner Formatierung würde ich normalerweise nichts aussetzen, jedem das seine. Allerdings hat mich die Platzierung der JOIN-Schlüsselwörter doch sehr, äh, frustriert
Weil ich es so weit nach links schob? Irgendwie zur Gewohnheit geworden... vielleicht hast du mich aber hier ein wenig überzeugt, es übersichtlicher darzustellen 😉

Schön, das es läuft. Ich konnte mir vor allem auf SD.[DISPO] IN ( 'Y78','Y79' ) nicht so richtig einen Reim darauf machen, wann was der Fall ist.
Leider ich so auch nicht, da das am Ende Einstellungen seitens unserer Arbeitsvorbereitung sind. Aber nur so viel, dass der Disponent Y79 allgemein-gesagt eine Untergruppe zum Disponenten Y78 ist. Zumindest lautet so die Theorie...

Aber nochmal vielen Dank dafür...
 
Zurück
Oben