Bernd: SUM / MAX

Hallo,

ich möchte für einen Projektzeitraum angezeigt bekommen wie viele Artikel ich maximal buchen kann. Meine Idee war

SELECT SUM(aa_menge) AS `summe_unterwegsProjektzeitraum` 
FROM artikel_ausgeliehen 

WHERE aa_status=2 

AND aa_artikelID=? 
AND aa_datum BETWEEN  ? AND ?

GROUP BY aa_artikelID, aa_datum 
        
LIMIT 1

Ergebnis

Ausgabe DB

Mein Ich habe 5 Artikel verfügbar, mein Zeitraum ist der 10.07.2019 - 14.07.2019. Die Prüfung im PHP lautet

if ($Ausgabe_TagesbestandProjektzeitraum <  $array['menge']): 
   $erlaubeBestellung = 0;

Laut Script passt alles, ich bekomme keine Fehlermeldung. Laut Ausgabe erhalte ich die Info, einen kann ich noch buchen. Würde auf den 10.07. und 14.07. passen, aber nicht durchgehend für den kompletten Zeitraum.

Jetzt kam ich auf die Idee anstatt SUM MAX zu nehmen, also so

SELECT MAX( aa_menge ) AS  `summe_unterwegsProjektzeitraum` ,  `aa_datum` AS Datum
FROM artikel_ausgeliehen

WHERE aa_status =2

AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
AND aa_datum

BETWEEN  '2019-07-10'

AND  '2019-07-14'
GROUP BY aa_artikelID, aa_datum

Als Ergebnis erhalte ich

Ausgabe DB - 2

Stimmt aber nicht, denn der größte Wert ist doch 5? Wie kann ich sonst meinen Projektzeitraum richtig prüfen?

  1. ich möchte für einen Projektzeitraum angezeigt bekommen wie viele Artikel ich maximal buchen kann.

    Denkfehler oder schräg formuliert? Wie willst du von ausgeliehenen Artikeln auf noch verfügbare schließen?

    Ich vermute, du möchtest in einem Zeitraum den Tag mit der maximal ausgeliehenen Stückzahl sehen und dann mit Hilfe anderer Quellen die Buchungsmenge errechnen.

    Du hast also pro Tag mehrere Ausleihen für denselben Artikel, deswegen summierst und gruppierst du nach Datum. In der Zahl können mehrere Ausleihen enthalten sein.

    Bei MAX greifst du aber die Ausleihe mit der höchsten Zahl, die anderen an diesem Tag werden ignoriert.

    Probiere bei SUM ein ORDER auf die Menge descending (absteigend), also der Tag mit der größten Menge zuerst. Und dann schneidest du mit LIMIT 0,1 alle weiteren Treffer ab.

    Linuchs

    1. Denkfehler oder schräg formuliert? Wie willst du von ausgeliehenen Artikeln auf noch verfügbare schließen?

      // Hier steht der Wert, der die DB ausspuckt
      $Ausgabe_TagesbestandProjektzeitraum 
      
      // Hier steht der Wert, den ich buchen möchte z.B. 6
      $array['menge']
      
      1. Okay, du hast deine zu buchende Wunsch-Menge und den Tag mit der größten ausgeliehenen Menge.

        Und nun?

        Du meinst, die ausgeliehene Menge kannst du nochmals ausleihen?

        Also, je mehr ausgeliehen wurde, desto mehr steht dir zur Verfügung?

        Verstehe ich nicht, bei mir wäre das gerade umgekehrt. Und ich müsste den Inventarbestand kennen. Wo ist der bei dir?

        Linuchs

  2. Tach!

    ...
    LIMIT 1
    

    Ergebnis

    Ausgabe DB

    Das passt nicht zusammen.

    Jetzt kam ich auf die Idee anstatt SUM MAX zu nehmen, also so ... Stimmt aber nicht, denn der größte Wert ist doch 5?

    Wenn in der Gruppe zum Beispiel die Werte 4 und 1 enthalten sind, muss zwar die Summe 5 ergeben, aber der Maximalwert kann nur 4 sein. MAX() wird genauso wie SUM() anhand der Datensätze der Gruppe ermittelt.

    Wenn du die Gruppe mit dem größten Wert haben möchtest, musst du die Max-Abfrage auf das Ergebnis der ersten Abfrage setzen, sprich ein Subselect erstellen.

    dedlfix.

    1. Hallo,

      wie Linuchs er vorgeschlagen hat, könnte ich es auch so umsetzten?

      SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
      FROM artikel_ausgeliehen
      
      WHERE aa_status =2
      
      AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
      AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
      
      GROUP BY aa_artikelID, aa_datum ORDER by `aa_menge`
      LIMIT 1
      

      Damit bekomme ich jetzt den höchsten Eintrag, oder laufe ich wieder Gefahr dass etwas nicht passt?

      1. Tach!

        wie Linuchs er vorgeschlagen hat, könnte ich es auch so umsetzten?

        SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
        FROM artikel_ausgeliehen
        
        WHERE aa_status =2
        
        AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
        AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
        
        GROUP BY aa_artikelID, aa_datum ORDER by `aa_menge`
        LIMIT 1
        

        Damit bekommst du die kleinste Menge der ausgeliehenen Artikel. Wenn du du aber wissen mcöhtest, wieviele maximal ausgeliehen sind, musst du die größte Menge nehmen. Linuchs hatte nicht umsonst von Rückwärtssortierung (DESC) geschrieben.

        Damit bekomme ich jetzt den höchsten Eintrag, oder laufe ich wieder Gefahr dass etwas nicht passt?

        Ich erteile keine Absolution, besonders nicht für Systeme, die ich nicht kenne. Du musst das schon selbst mit ausreichend Beispieldaten probieren, ob dein System so arbeitet, wie du es dir vorstellst.

        dedlfix.

      2. Hallo Bernd,

        falsch. ORDER liefert standardmäßig die kleinste(n) Menge(n) zuerst. Du musst die Reihenfolge mit DESCENDING unkehren.

        Und ein Gruppieren nach Artikel-ID ist überflüssig, wenn du ohnehin nur einen Artikel betrachtest.

        Linuchs

        1. Wenn ich dieses schreibe

          SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
          FROM artikel_ausgeliehen
          
          WHERE aa_status =2
          
          AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
          AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
          
          GROUP BY aa_artikelID, aa_datum ORDER by aa_menge DESC
          LIMIT 1
          

          erhalte ich folgendes

          DB

          Wenn ich folgendes schreibe

          SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
          FROM artikel_ausgeliehen
          
          WHERE aa_status =2
          
          AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
          AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
          
          GROUP BY aa_artikelID, aa_datum ORDER by aa_menge ASC
          LIMIT 1
          

          erhalte ich folgendes

          DB 1

          Wenn ich jetzt hingegen folgendes schreibe

          SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
          FROM artikel_ausgeliehen
          
          WHERE aa_status =2
          
          AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
          AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
          
          GROUP BY aa_datum ORDER by aa_menge ASC
          LIMIT 1
          

          erhalte ich

          DB 2

          Und wenn ich den letzten Test mache

          SELECT SUM( aa_menge ) AS  `summe_unterwegsProjektzeitraum`
          FROM artikel_ausgeliehen
          
          WHERE aa_status =2
          
          AND aa_artikelID =  '488f3f36c073c45f5f4622073e2d873b'
          AND aa_datum BETWEEN  '2019-07-10' AND  '2019-07-14'
          
          GROUP BY aa_datum ORDER by aa_menge DESC
          LIMIT 1
          

          erhalte ich wie zuvor folgendes

          DB 3

          Da stimmt doch überhaupt nichts mehr. Ich werde noch kirre.

          Und ein Gruppieren nach Artikel-ID ist überflüssig, wenn du ohnehin nur einen Artikel betrachtest.

          Doch die benötige ich, denn es kann für einen Tag auch mehrere Einträge pro Artikel vorkommen.

          1. Tach!

            Da stimmt doch überhaupt nichts mehr. Ich werde noch kirre.

            Wonach sortierst du überhaupt? Möchtest du die größte Summe, musst du nach der Summe sortieren, nicht nach einem Einzeldatensatzwert.

            Und ein Gruppieren nach Artikel-ID ist überflüssig, wenn du ohnehin nur einen Artikel betrachtest.

            Doch die benötige ich, denn es kann für einen Tag auch mehrere Einträge pro Artikel vorkommen.

            Wenn die WHERE-Einschränkung auf die Artikel-ID nur zum Test drin ist, dann irritiert das, wenn da gleichzeitig eine Gruppierung auf die ID zu sehen ist, weil eine Gruppierung auf einen Einzelwert keine Gruppen erzeugen kann, außer der die sowieso da ist.

            dedlfix.

          2. Hallo Bernd,

            mal schauen, ob wir den Knoten aufbekommen.

            Und ein Gruppieren nach Artikel-ID ist überflüssig, wenn du ohnehin nur einen Artikel betrachtest.

            Doch die benötige ich, denn es kann für einen Tag auch mehrere Einträge pro Artikel vorkommen.

            Mit AND aa_artikelID = '488f3f36c073c45f5f4622073e2d873b' suchst du nach allen Sätzen eines bestimmten Artikels, von daher kann gar kein anderer Artikel gefunden werden. Wenn du an einem Tag mehrere Einträge zu diesem Artikel hast, ist es immer noch nur dieser Artikel.

            Von allen Datensätzen dieses Artikels greifst du nun diejenigen in einem bestimmten Zeitfenster: AND aa_datum BETWEEN '2019-07-10' AND '2019-07-14' Pro Tag können das 0 .. n Datensätze sein.

            Mit SUM und ORDER BY datum erhälst du die Summe der ausgeliehenen Stücke an diesem Datum für diesen Artikel.

            AAABER: Du nennst die Summe summe_unterwegsProjektzeitraum, sortierst aber nach aa_menge DESC das ist nicht die gewollte Summe, sondern der Wert aus (irgend) einem der beteiligten Sätze. Einen Satz mit 5 hast du nicht. Womöglich ist bei der nächsten Suche die Antwort 1, denn auch so einen Satz hast du an diesem Tag.

            Linuchs

  3. Hallo,

    was mir nicht ganz klar ist: es scheint sich fachlich ja so etwas wie eine Bibliothek zu handeln, bei dem man Dinge (Artikel) ausleihen kann. Nun ist es ja so, dass ich einen Artikel für einen Zeitraum ausleihen kann, und natürlich kann man dann eine Statistik machen, wieviele Artikel an jedem einzelnen Tag verliehen sind. Aber nur weil die Anzahl der verliehenen Artikel an jedem Tag kleiner als die Anzahl der verfügbaren Artikel ist, sagt mir das doch nichts darüber aus, ob ich auch einen Artikel über den gesamten Zeitraum ausleihen kann.

    Oder werden deine Artikel immer abends zurückgegeben?

    Wenn du wirklich eine mehrtägige Ausleihe erlauben willst, wirst du, denke ich, nicht darin umhinkommen, pro Artikel die Verfügbarkeit darzustellen und die Ressource einzeln zu verplanen.

    Viele Grüße Matti

    1. Ich würde für jede Ausleihe mit einem Datensatz hinkommen.

      Sowas mache ich für Events meines Kalenders. Ein Festival oder eine Ausstellung läuft über 1 .. n Tage. Da gibt es halt die Datenfelder tag und tag_bis

      Wenn ich die Evets eines Zeitraums sehen will, ist dies Teil der Abfrage:

      AND         (trm1.tag >= '".addslashes($arr_in['tag_von'])."' OR  trm1.tag_bis >= '".addslashes($arr_in['tag_von'])."' )
      AND         (trm1.tag <= '".addslashes($arr_in['tag_bis'])."' OR  trm1.tag_bis <= '".addslashes($arr_in['tag_bis'])."' )
      

      Dieses BETWEEN habe ich hier erst kennengelernt. muss ich mal ausprobieren.

      Linuchs

    2. Tach!

      Nun ist es ja so, dass ich einen Artikel für einen Zeitraum ausleihen kann, und natürlich kann man dann eine Statistik machen, wieviele Artikel an jedem einzelnen Tag verliehen sind. Aber nur weil die Anzahl der verliehenen Artikel an jedem Tag kleiner als die Anzahl der verfügbaren Artikel ist, sagt mir das doch nichts darüber aus, ob ich auch einen Artikel über den gesamten Zeitraum ausleihen kann.

      Warum nicht? Gibt es Szenarien, wo sich Ausleihe und Rückgabe so überschneiden, dass die Anzahl der ausgeliehenen Artikel trotzdem gleich bleibt und somit scheinbar Potential vorhanden wäre?

      dedlfix.

      1. Hi,

        ich bin gedanklich bei einer Raumbuchung, wo es häufig vorkommt, dass Meetings so gebucht werden, dass die Buchung von weiteren, längeren Meetings unmöglich wird, weil kleinere Meetings unglücklich die Räume ausgewählt haben. Bei austauschbaren Artikeln, die nicht im Voraus separat gebucht werden, wird das wohl funktionieren, da muss ich meinen Einwand zurückziehen.

        Beispiel: Ich habe hier fünf aufeinanderfolgende Tage, 3 zu buchende Ressourcen. In die Zelle schreibe ich jeweils eine Ressourcenbuchungs-Nummer für diesen Tag, wobei eine Buchung mehrere aufeinanderfolgende Tage umfassen kann. Die letzte Zeile enthält die Anzahl der gebuchten Ressourcen.

        Ressource Tag 1 Tag 2 Tag 3 Tag 4 Tag 5
        R1 B1 B1 B2 B2
        R2 B3 B3 B4
        R3 B5 B6 B6
        Gebucht 2 2 2 2 2

        Die Fachlichkeit im Falle von komplett austauschbaren Artikeln, die nicht einzeln im Vorhinein gebucht werden, kann natürlich anders sein. Es ist auch im Beispiel der Buchungsanfragen möglich, diese so zu verteilen, dass eine Buchung 7 von Tag 1 bis Tag 5 inkl. mit der selben Ressource möglich ist.

        Ressource Tag 1 Tag 2 Tag 3 Tag 4 Tag 5
        R1 B1 B1 B6 B6 B4
        R2 B5 B3 B3 B2 B2
        R3
        Gebucht 2 2 2 2 2

        Viele Grüße Matti

        1. Tach!

          ich bin gedanklich bei einer Raumbuchung, wo es häufig vorkommt, dass Meetings so gebucht werden, dass die Buchung von weiteren, längeren Meetings unmöglich wird, weil kleinere Meetings unglücklich die Räume ausgewählt haben. Bei austauschbaren Artikeln, die nicht im Voraus separat gebucht werden, wird das wohl funktionieren, da muss ich meinen Einwand zurückziehen.

          Ja, eben. Wenn ein Artikel von Mittwoch bis Freitag geplant ist, dann kann dieser trotzdem von Montag bis Freitag ausgeliehen werden, solange spätestens Dienstag einer reinkommt, der dann anstelle des ersten am Mittwoch rausgeht. Genaugenommen gibts da gar keinen Zusammenhang zwischen den Artikeln. Solange der Maximalwert über die Summen der gewünschten Tage kleiner als die Anzahl der generell vorhandenen Artikel bleibt, muss das aufgehen.

          dedlfix.