Ankündigung

Einklappen
Keine Ankündigung bisher.

Verständnisfrage GROUP BY

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Verständnisfrage GROUP BY

    Artikel_id | VK | MwS. | Menge

    Code:
    SELECT
      SUM(VK / MwSt* Menge) as nettoumsatz
    GROUP BY article_id
    Ich hab jetzt hier absichtlich die im Select verwendeten Felder im GROUP BY rausgelassen. Was würde dabei schiefgehen?


  • #2
    zum ganz langsammen Mitschreiben (Hammer, Meisel, Steinplatte): jede Spalte im Resultat muß entweder aggregiert oder gruppiert sein.
    PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

    Kommentar


    • #3
      Ich wollte es eigentlich so schreiben, sind VK und MwSt dann auch aggregiert?
      Code:
       SELECT
        SUM(Menge) * VK / MwSt as nettoumsatz
      GROUP BY article_id

      Kommentar


      • #4
        vermutlich wirst Du die article_id mit anzeigen wollen, und vermutlich wirst Du sum(menge * vk / mwst) wissen wollen...
        PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

        Kommentar


        • #5
          Rechnerisch sollten
          SUM(Menge) * VK / MwSt und sum(menge * vk / mwst) doch das gleiche sein? Muss ich im ersten Beispiel dann VK im Group By aufführen oder nicht? Ich frage, weil ich sowas verwendet habe
          $sold = "SUM(`menge`)"; und dann $sold in der Abfrage an mehreren Stellen verwende.

          Kommentar


          • #6
            Code:
            test=*# select article, sum(sold * vk / mwst) from sold group by article limit 0;
             article | sum
            ---------+-----
            (0 rows)
            
            test=*# select article, sum(sold) * vk / mwst from sold group by article limit 0;
            FEHLER:  Spalte »sold.vk« muss in der GROUP-BY-Klausel erscheinen oder in einer Aggregatfunktion verwendet werden
            LINE 1: select article, sum(sold) * vk / mwst from sold group by art...
                                                ^
            test=*#
            Installier Dir doch einfach PostgreSQL, zumindest zum testen. In Production kannst dann immer noch MySQL verwenden und Dich über lustige Dinge wie in https://datenbankforum.com/threads/g...l-und-pg.4859/ beschrieben erfreuen.
            PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

            Kommentar


            • #7
              Code:
              SELECT
                (SUM(Menge) * VK / MwSt) as nettoumsatz
              GROUP BY article_id, VK, MwSt
              Du hast hier aber wieder englisch/deutsch Mischmasch.

              Kommentar


              • #8
                Code:
                Installier Dir doch einfach PostgreSQL, zumindest zum testen. In Production kannst dann immer noch MySQL verwenden und Dich über lustige Dinge wie in https://datenbankforum.com/threads/g...l-und-pg.4859/ beschrieben erfreuen.
                Guter Tipp, das werde ich machen.

                Kommentar


                • #9
                  Also zuerst mal ergibt VK / MwSt * Menge nicht den Nettoumsatz. Vorausgesetzt, mit MwSt ist der Mehrwertsteuer-Satz (z.B. 19%) gemeint, muß es VK / (1 + MwSt) * Menge = Postensumme Netto lauten.
                  Dann: Es muß zwingend sum(VK/(1+MwSt)*Menge) heißen.
                  Dann: Du solltest ein wenig, auch bei deinen Beiträgen hier, auf Konsistenz achten: Oben schreibst du „MwS.“ (der Punkt geht in einem Feldnamen überhaupt nicht!!), im SQL dann „MwSt“.
                  Mit der Verwendung von PostgreSQL oder MySQL hat das ganze nichts zu tun, den Umweg kannst du dir sparen.
                  Zu deiner Frage: Es geht die Abfrage „schief“, weil sie einen Fehler erzeugt. Das liegt aber offenbar an dem fehlenden FROM-clause. Mit dem geht es und liefert auch ein korrektes Ergebnis. Ob letzteres an der gegebenen Datenkonstellation liegt, kann ich ggw. nicht beurteilen, dazu müsste man mal ein paar mehr geeignete Testdaten haben und ein bissle überlegen.
                  Ich habe die Abfrage so eingegeben:
                  Code:
                  SELECT Round(Sum(Menge*VK/(1+MwSt)),2) AS nettoumsatz FROM tbl_Verkauf GROUP BY tbl_Verkauf.article_id
                  Ich würde, auch, weil du ja die Summen pro Artikel willst, den Artikel in die Feldaufzählung reinnehmen.

                  Der wichtigste Grundsatz ist, daß alle Felder, die in der Feldauflistung vorkommen (nicht einzeln bei Berechnungen) auch entweder in einer Aggregatfunktion oder in der Gruppierung auftauchen müssen.

                  Kommentar


                  • #10
                    Zitat von Alf2016 Beitrag anzeigen
                    Der wichtigste Grundsatz, daß nämlich alle Felder, die in der Feldauflistung vorkommen (nicht einzeln bei Berechnungen) -- rest ausgeblendet
                    Das hatten wir schon im Dutzend deutlich präziser.

                    Kommentar


                    • #11
                      Zitat von Perry Staltic Beitrag anzeigen

                      Das hatten wir schon im Dutzend deutlich präziser.
                      Du kannst es gerne "deutlich präziser" formulieren, ändert aber doch nichts daran, daß es im Zusammenhang mit dem GROUP BY-Statement der wichtigste Grundsatz ist. Und warum du ausgerechnet das, was den Grundsatz ausmacht in deinem Zitat ausblendest - ziemlich schleierhaft...

                      phpP Ich habe den Grundsatz vor allem deshalb wiederholt (neben dem, daß er tatsächlich das Wichtigste an der Sache ist), weil du dich in deinem Eingangspost ja offenbar auf das Vorkommen der "weggelassenen Spalten" VK und MwSt in der Berechnung beziehst. Hierzu mal ein Zahlenbeispiel:

                      Code:
                      article_id | VK | MwSt | Menge
                      -----------|------|------|-----
                         1       | 2,95 | 0,19 | 2
                         1       | 3,00 | 0,07 | 1
                         2       | 1,29 | 0,19 | 3
                         2       | 1,29 | 0,07 | 1
                      Falls SQL - egal in welcher "Spielart" - dich dazu "zwingt", VK und MwSt in die Gruppierung einzubeziehen, werden 4 Gruppen gebildet und weder die Tatsache, daß du 2mal article_id 1 bzw. 2 hast noch daß der Verkaufspreis für 2 in beiden Datensätzen gleich ist, kann das verhindern. Mag sein, daß du solche Gruppen möchtest, aber für jemanden, der insgesamt Summen pro Artikel will, wäre das falsch. Abgesehen davon sind nach dem o.g. Grundsatz die beiden Spalten ja einbezogen, nämlich in die Aggregat-Funktion.

                      Edit: Sehe gerade, daß du in #3 explizit danach gefragt hattest, habe das zu dem Zeitpunkt entweder überlesen oder anders eingeordnet. Antwort: Nicht MwSt und VK, sondern beide zusammen in der Berechnung des Summanden VK / (1 + MwSt) * Menge, der in der Abfrage "als solcher" Datensatz für Datensatz berechnet wird, bevor er zur Summe aggregiert wird. Ob der Grundsatz nun eingehalten wird, weil MsSt und VK "implizit" in oben beschriebener Weise aggregiert werden, oder weil sie explizit nicht im Resultat vorhanden sind und deshalb nicht in der Gruppierung auftauchen müssen, ist unerheblich. Entscheidend ist, daß jedes DBMS, ob MySQL, PostgreSQL oder der Weihnachtsmann, das das verhindern möchte, "Schrott" ist.

                      Kommentar


                      • #12
                        Der Grund warum ich ausgerechnet den "Grundsatz" ausgeblendet habe: er ist mehr als irreführend formuliert. Außerdem ist es auch -besser formuliert- kein Grundsatz, sondern nicht mehr als eine Faustregel, wie ich es nenne, denn es gibt viele Ausnahmen.
                        Tatsächlich ist mysql nicht das einzige System, was "Sonderregeln" für Group by "anbietet". mySQL ist nur das mit der wahrscheinlich schlechtesten Umsetzung. Ich habe neulich erst gelernt, das auch SQLite ähnliche Klopper bringt und "Besonderheiten" bieten alle Systeme.
                        Die Faustregel fasst dabei den funktional kleinsten, gemeinsamen Nenner verschiedener RDBMS -oder sagen wir einfach: das Prinzip- zusammen, so dass man nicht stundenlang nachschlagen oder überlegen muss und sie ist selbst so kompakt wie möglich. "Faustregel" auch deshalb, weil ich die Diskussion (".. bei mir geht aber auch ...") gar nicht führen will. Sie ist ja für Einsteiger gedacht. Stimmen soll sie halt trotzdem!

                        Meine ideale Formulierung lautet daher inkl. der Bezeichnung:
                        Faustregel "Group by": Jede Spalte in der Selectclause muss entweder aggregiert oder gruppiert werden.
                        (Im Übrigen ohne diese penible Auslegung ziemlich genau das, was akretschmer schon im 2. Beitrag schrieb und damit wäre der Thread ohne die "Verunstaltung" im 2. Anlauf ausgekommen.)

                        Jenseits von Mehrwertsteuer und Verkaufspreisen bedeutet das zum wirklichen Verständnis:
                        1. Implizit: Wenn im Select erst gar kein Aggregat erstellt wird, so wird auch kein Group by benötigt!
                        (schon das ignorieren viele, weil sie einen diffuses Ordnungs / Sortierungswunsch haben und Group by eben noch nicht richtig verstanden haben)
                        2. Was ist überhaupt ein Aggregat?
                        Eine Zusammenfassung von Werten und zwar eine "vertikale" Zusammenfassung, eine über mehrere (>1) Datensätze hinweg. Sehr beliebt SUM(), es gibt natürlich mehr Aggregatfunktionen, siehe Doku!

                        Das ist eigentlich schon alles!

                        1 zu 1 angewendet ergibt sich im Beispiel:

                        für die Summierung aller Lagerartikel
                        PHP-Code:
                        select sum(onstockfrom stock
                        > keine nicht-aggregierte Spalte wird ausgegeben, also
                        > kein Group by

                        zusätzlich für das gebundene Geld im Lager:
                        PHP-Code:
                        select sum(onstock), sum(purchase_price*onstockfrom stock
                        > immer noch keine nicht-aggregierte Spalte dabei, also
                        > kein Group by


                        wie oben aber mit Ausgabe des Lagers:
                        PHP-Code:
                        select stock_sitesum(onstock), sum(purchase_price*onstock)
                          
                        from stock
                         group by stock_site

                        > Ah! Eine nicht aggregierte Spalte wird ausgegeben,
                        > sie gehört in die Group by Clause! Also der erste Anlass hier, überhaupt Group by zu nutzen!

                        spannende Varianten
                        PHP-Code:
                        select stock_sitesum(onstock) as anzahl,
                               
                        sum(purchase_price*onstock) as EK,
                               
                        sum(selling_price*onstock ) *  1.19 as VK
                          from stock
                         group by stock_site

                        > ok, eine Konstante ist von ihrer Natur her schon ziemlich "gruppiert"
                        > keine Änderung am Group by erforderlich

                        jetzt mit verschiedenen Mehrwertsteuersätzen:
                        PHP-Code:
                        select stock_sitesum(onstock) as anzahl,
                               
                        sum(purchase_price*onstock) as EK,
                               
                        sum(selling_price*onstock ) * (case when vat_class 1 then 1.19 when vat_class 2 then 1.07 end ) as VK
                          from stock
                         group by stock_site
                        vat_class
                        > Hier wird anhand der Mehrwertsteuerklasse je Artikel enschieden, das Feld muss gruppiert werden.
                        Rein rechnerisch gibt es in diesem Fall aber auch folgende Möglichkeit
                        PHP-Code:
                        select stock_sitesum(onstock) as anzahl,
                               
                        sum(purchase_price*onstock) as EK,
                               
                        sum(selling_price*onstock * (case when vat_class 1 then 1.19 when vat_class 2 then 1.07 end ))  as VK
                          from stock
                         group by stock_site

                        Das macht vielleicht die "Faustregel" deutlicher. Das fragliche Feld wurde nun innerhalb der Aggregat Funktion platziert statt außerhalb, damit ist keine Nennung in der Group Clause notwendig, bzw. gewollt. (Auch interessant: Man könnte das machen, aber das ergibt etwas ganz anderes.)

                        Kommentar


                        • #13
                          Zitat von Perry Staltic Beitrag anzeigen
                          ...

                          jetzt mit verschiedenen Mehrwertsteuersätzen:

                          PHP-Code:
                          select stock_sitesum(onstock) as anzahl,
                          sum(purchase_price*onstock) as EK,
                          sum(selling_price*onstock ) * (case when vat_class 1 then 1.19 when vat_class 2 then 1.07 end ) as VK
                          from stock
                          group by stock_site
                          vat_class
                          ...
                          Hier fragt sich: Woher kommt "vat_class"? Antwort: Normalerweise aus den Artikelstammdaten, wie auch VK. Was aber, wenn sowohl VK als auch MwSt für denselben Artikel verschieden sein können? Antwort: Hier schließen sich eine Menge Fragen an, die auf Grundlage des unvollkommenen Datenmodells natürlich nicht zu beantworten sind.

                          Offenbar genügt dem TE dieses Modell aber. Da kann man jetzt drüber nachdenken, ob man - wie hier allgemein üblich - ihm ein "Sich-Einlesen" in Datenbanken empfiehlt (immerhin ist das hier die Rubrik DB). Kann man.

                          Daß die obige unsägliche Kontrollstruktur in einer Abfrage bei einem "richtigen" Datenmodell in einen entspr. Join wandern würde, muß dann auch nicht mehr erwähnt werden...

                          Edit: Zum Mehrwertsteuersatz mal ein Ergebnis aus dem "Schnell-Googlen": http://www.abzonline.de/praxis/steue...069282796.html
                          Müsste man dann natürlich bei Bedarf entspr. anders ableiten.

                          Kommentar


                          • #14
                            Perry Staltic Alle deine Beispiele entsprechen doch deiner Faustregel, also kann man schon von einem Grundsatz reden. Also macht für dich die Tatsache, dass MySQL / SQLite dies nicht als Fehler erkennen und wirre Ergebnisse liefern, die Grundregel zur Faustregel?
                            Oder hast du auch SQL Beispiele für die von dir genannten Ausnahmen wo korrekte Ergebnisse rauskommen?
                            Ich finde gerade als Einsteiger sollte man sich das schon als Grundsatz merken und nicht als Faustregel.

                            Kommentar


                            • #15
                              Zitat von Meister1900 Beitrag anzeigen
                              Perry Staltic Alle deine Beispiele entsprechen doch deiner Faustregel, also kann man schon von einem Grundsatz reden. Also macht für dich die Tatsache, dass MySQL / SQLite dies nicht als Fehler erkennen und wirre Ergebnisse liefern, die Grundregel zur Faustregel?
                              Oder hast du auch SQL Beispiele für die von dir genannten Ausnahmen wo korrekte Ergebnisse rauskommen?
                              Ich finde gerade als Einsteiger sollte man sich das schon als Grundsatz merken und nicht als Faustregel.
                              Wo erkennt denn MySQL was nicht als Fehler und liefert welche wirren Ergebnisse? Beispiel von Perry Staltic, vom TE oder von Dir, bitte.

                              Kommentar

                              Lädt...
                              X