Neu Artikelverwaltung -> Detaillierte Kindartikelansicht mit Absatz nach Zeiträumen, Lagerreichweite, Zulauf und Retourenquote

Thomas Lisson

Administrator
Mitarbeiter
24. März 2006
15.574
299
Köln
Hi zusammen,

für all diejenigen, die viel mit Variationskombinationen arbeiten, ist diese LVE (Listviewextension) sinnvoll. Ihr klickt auf einen Varkombi-Vaterartikel und seht wesentlich mehr Informationen aller Kinder dieses Vaters - siehe Bild im Anhang.
Ich hab das nicht in sehr großen Datenbanken getestet - gebt gerne Feedback, ob es performant ist.

SQL:
SELECT    tartikel.cArtNr AS ArtNr,
        tArtikelBeschreibung.cName AS Artikelname,    
        ROUND(CONVERT(FLOAT, vLagerbestandEx.fVerfuegbar), 2) AS 'Verfügbar',
        ROUND(CONVERT(FLOAT, vLagerbestandEx.fZulauf), 2) AS 'Zulauf',
        CASE
            WHEN ISNULL(jLetzte365Tage.absatz, 0) > 0 THEN ROUND(CONVERT(FLOAT, vLagerbestandEx.fVerfuegbar / (ISNULL(jLetzte365Tage.absatz, 0) / 365)), 1)
            ELSE 9999
        END AS 'Lagerreichweite (in Tagen)',
        ISNULL(jLetzte30Tage.absatz, 0) AS 'Absatz 30 Tage',
        ISNULL(jLetzte90Tage.absatz, 0) AS 'Abs. 90 Tage',
        ISNULL(jLetzte365Tage.absatz, 0) AS 'Abs. 365 Tage',
        ISNULL(jAbsatzGesamt.absatz, 0) AS 'Abs. Gesamt',
        ISNULL(jVKDurchschnitt.vk, 0) AS 'Ø VK-Brutto',
        ISNULL(jRetourenGesamt.Retourenquote, '0%') AS 'Retourenquote',
        CASE
            WHEN ISNULL(jLetzte365Tage.anzahlAuftraege, 0) > 0 THEN ROUND(CONVERT(FLOAT, jLetzte365Tage.absatz / ISNULL(jLetzte365Tage.anzahlAuftraege, 0)), 1)
            ELSE 0
        END AS 'Ø Bestellmenge'
FROM tartikel
JOIN dbo.tSpracheUsed ON nStandard = 1
JOIN dbo.tArtikelBeschreibung ON tArtikelBeschreibung.kArtikel = tartikel.kArtikel
    AND tArtikelBeschreibung.kSprache = tSpracheUsed.kSprache
    AND tArtikelBeschreibung.kPlattform=1
LEFT JOIN vLagerbestandEx ON vLagerbestandEx.kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -30, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte30Tage ON jLetzte30Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -90, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte90Tage ON jLetzte90Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz,
        COUNT(DISTINCT(tbestellung.kBestellung)) AS anzahlAuftraege
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -365, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte365Tage ON jLetzte365Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
    GROUP BY tArtikel_kArtikel
) AS jAbsatzGesamt ON jAbsatzGesamt.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(AVG(tbestellpos.fVKPreis), 0.0)), 2) AS vk
    FROM tbestellpos
    JOIN tBestellung ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
    GROUP BY tArtikel_kArtikel
) AS jVKDurchschnitt ON jVKDurchschnitt.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
SELECT jabsatzgesamt.tArtikel_kArtikel,
        CONCAT((ISNULL(retourengesamt.rm, 0.0)/jabsatzgesamt.absatz)*100, '%') as Retourenquote
FROM
(SELECT tArtikel_kArtikel,
    ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tbestellung.cType = 'B'
        AND tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
    GROUP BY tArtikel_kArtikel) AS jabsatzgesamt
LEFT JOIN
    (SELECT kArtikel,
        ROUND(CONVERT(FLOAT, ISNULL(SUM(tRMRetourePos.fAnzahl), 0.0)), 2) AS rm
    FROM tbestellung
    JOIN tRMRetoure ON tRMRetoure.kBestellung = tBestellung.kBestellung
    JOIN tRMRetourePos ON tRMRetourePos.kRMRetoure = tRMRetoure.kRMRetoure
    GROUP BY kArtikel) AS retourengesamt on retourengesamt.kArtikel=jabsatzgesamt.tArtikel_kArtikel)
        as jRetourenGesamt on jRetourenGesamt.tArtikel_kArtikel = tartikel.kArtikel
WHERE kVaterArtikel = @Key
ORDER BY cArtNr

Edit am 02.12.2019 16:00 - Lagerführung muss nicht mehr aktiv sein

Viel Spaß damit!
 

Anhänge

  • LVE_Kindartikel detailliert.png
    LVE_Kindartikel detailliert.png
    32,2 KB · Aufrufe: 244
Zuletzt bearbeitet:

Omnideal-Böhling

Gut bekanntes Mitglied
30. April 2015
286
20
Hi zusammen,

für all diejenigen, die viel mit Variationskombinationen arbeiten, ist diese LVE (Listviewextension) sinnvoll. Ihr klickt auf einen Varkombi-Vaterartikel und seht wesentlich mehr Informationen aller Kinder dieses Vaters - siehe Bild im Anhang.
Ich hab das nicht in sehr großen Datenbanken getestet - gebt gerne Feedback, ob es performant ist.

SQL:
SELECT    tartikel.cArtNr AS ArtNr,
        tArtikelBeschreibung.cName AS Artikelname,      
        ROUND(CONVERT(FLOAT, vLagerbestandEx.fVerfuegbar), 2) AS 'Verfügbar',
        ROUND(CONVERT(FLOAT, vLagerbestandEx.fZulauf), 2) AS 'Zulauf',
        CASE
            WHEN ISNULL(jLetzte365Tage.absatz, 0) > 0 THEN CONCAT(ROUND(CONVERT(FLOAT, vLagerbestandEx.fVerfuegbar / (ISNULL(jLetzte365Tage.absatz, 0) / 365)), 1), ' Tage')
            ELSE 'unendlich'
        END AS 'Lagerreichweite',
        ISNULL(jLetzte30Tage.absatz, 0) AS 'Absatz 30 Tage',
        ISNULL(jLetzte90Tage.absatz, 0) AS 'Abs. 90 Tage',
        ISNULL(jLetzte365Tage.absatz, 0) AS 'Abs. 365 Tage',
        ISNULL(jAbsatzGesamt.absatz, 0) AS 'Abs. Gesamt',
        ISNULL(jVKDurchschnitt.vk, 0) AS 'Ø VK-Brutto',
        ISNULL(jRetourenGesamt.Retourenquote, '0%') AS 'Retourenquote'
FROM tartikel
JOIN dbo.tSpracheUsed ON nStandard = 1
JOIN dbo.tArtikelBeschreibung ON tArtikelBeschreibung.kArtikel = tartikel.kArtikel
    AND tArtikelBeschreibung.kSprache = tArtikelBeschreibung.kSprache
    AND tArtikelBeschreibung.kPlattform=1
JOIN vLagerbestandEx ON vLagerbestandEx.kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -30, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte30Tage ON jLetzte30Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -90, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte90Tage ON jLetzte90Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
        AND tBestellung.dErstellt > DATEADD(DAY, -365, getdate())
    GROUP BY tArtikel_kArtikel
) AS jLetzte365Tage ON jLetzte365Tage.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
    GROUP BY tArtikel_kArtikel
) AS jAbsatzGesamt ON jAbsatzGesamt.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
    SELECT tArtikel_kArtikel, ROUND(CONVERT(FLOAT, ISNULL(AVG(tbestellpos.fVKPreis), 0.0)), 2) AS vk
    FROM tbestellpos
    JOIN tBestellung ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
        AND tbestellung.cType = 'B'
    GROUP BY tArtikel_kArtikel
) AS jVKDurchschnitt ON jVKDurchschnitt.tArtikel_kArtikel = tartikel.kArtikel
LEFT JOIN (
SELECT jabsatzgesamt.tArtikel_kArtikel,
        CONCAT((ISNULL(retourengesamt.rm, 0.0)/jabsatzgesamt.absatz)*100, '%') as Retourenquote
FROM
(SELECT tArtikel_kArtikel,
    ROUND(CONVERT(FLOAT, ISNULL(SUM(tbestellpos.nAnzahl), 0.0)), 2) AS absatz
    FROM tbestellung
    JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
    WHERE tbestellung.cType = 'B'
        AND tBestellung.nStorno = 0 -- Stornierte Aufträge nicht beachten
    GROUP BY tArtikel_kArtikel) AS jabsatzgesamt
LEFT JOIN
    (SELECT kArtikel,
        ROUND(CONVERT(FLOAT, ISNULL(SUM(tRMRetourePos.fAnzahl), 0.0)), 2) AS rm
    FROM tbestellung
    JOIN tRMRetoure ON tRMRetoure.kBestellung = tBestellung.kBestellung
    JOIN tRMRetourePos ON tRMRetourePos.kRMRetoure = tRMRetoure.kRMRetoure
    GROUP BY kArtikel) AS retourengesamt on retourengesamt.kArtikel=jabsatzgesamt.tArtikel_kArtikel)
        as jRetourenGesamt on jRetourenGesamt.tArtikel_kArtikel = tartikel.kArtikel
WHERE kVaterArtikel = @Key
ORDER BY cArtNr

Viel Spaß damit!
Hi Thomas,

auch hier ist glaube ich ein kleiner Bug drin .Mir werden die Artikel wieder mehrmals angezeigt.
 

Seulberg

Sehr aktives Mitglied
14. Januar 2012
647
40
Hallo,
Super, vielen Dank

hier könnte man bestimmt noch etwas einbauen, damit das hier automatisch ausgeführt wird "Optionale Breite (alle Spalten)" oder?

Gruß
Johann
 
  • Gefällt mir
Reaktionen: gnarx

hula1499

Sehr aktives Mitglied
22. Juni 2011
5.259
1.195
Also, diese "Eigene Übersichten" ist ja vollkommen an mir vorbeigegangen, echt super Sache!!!

Ich hab hier auch doppelte Einträge, hier werden die Sprachen doppelt aufgelistet (also für jede Sprache ein Eintrag).
 

rosi

Aktives Mitglied
19. November 2014
21
0
wirklich toll was hier alles gebaut wird!

Die Sortierung nach lagerreichweite funktioniert so nicht. Vielleicht nur ganze zahl ausgeben lassen
 

xadoX

Sehr aktives Mitglied
11. September 2012
622
48
Könnte man in diesen sensationellen SQL noch um die durchschnittliche Bestellmenge des Artikels pro Auftrag ergänzen?

Also Verkaufte Menge pro Jahr / Vorkommen in Aufträgen pro Jahr

Diese Kennzahl ist für den Einkauf sehr interessant. Wird bei Absatz der letzten 30 Tage eine 100 angezeigt, wurde der Artikel jedoch nur von einem einzigen Kunden bestellt, dann sollte man sich zwei Mal überlegen, ob man sich weitere 100 auf Lager legt. Gibt es jedoch in den letzten 30 Tagen 100 verschiedene Aufträge mit jeweils Menge 1, dann macht es deutlich mehr Sinn sich den Artikel aufs Lager zu legen.
 

knackig

Sehr aktives Mitglied
17. November 2011
952
156
Nordhessen
Macht Sinn, haben wir in SQL oben ergänzt

Funktioniert es in der letzten angepassten Version? Wenn ich es so 1 zu 1 einfüge, bekomme ich nur die Info "Keine Daten vorhanden" obwohl der Artikel definitiv Kinder hat, die schon Verkaufshistorie haben.

EDIT: SSMS spuckt dabei den folgenden Fehler aus:
SQL:
Meldung 208, Ebene 16, Status 1, Zeile 1
Ungültiger Objektname "tartikel".
 
Zuletzt bearbeitet:

Thomas Lisson

Administrator
Mitarbeiter
24. März 2006
15.574
299
Köln