Nik: mysql Brett vorm Kopf

Hi,

wer sieht, was ich grade nicht sehe?

  
SUM(ze.Nettozahlung),  
ROUND(SUM(ze.Nettozahlung*(ze.USt/100)),2)  

ergibt 159 und 30,21

  
SUM(ze.Nettozahlung  
*(CASE  
WHEN r.Belegart  = 'RE' THEN 1  
WHEN r.Belegart = 'GU' THEN (-1)  
WHEN r.Belegart = 'ST' THEN (-1)  
END)  
),  
ROUND(SUM(ze.Nettozahlung*(ze.USt/100)  
*(CASE  
WHEN r.Belegart = 'RE' THEN 1  
WHEN r.Belegart = 'GU' THEN (-1)  
WHEN r.Belegart = 'ST' THEN (-1)  
END)  
),2)  

ergibt NULL NULL

bei demselben JOIN im weiteren Teil der Query.

Die Spalte r.Belegart ist definitiv existent und kann ausschließlich RE, GU oder ST beinhalten.

Nik

  1. Tach!

    ergibt NULL NULL

    Wenn NULL als Ergebnis rauskommt, war irgendwo ein NULL beteiligt.

    bei demselben JOIN im weiteren Teil der Query.

    Von einem Join ist in deinem Posting nichts zu sehen.

    dedlfix.

    1. Hi,

      Wenn NULL als Ergebnis rauskommt, war irgendwo ein NULL beteiligt.

      Hab ich mal kontrolliert, ist aber nicht der Fall. Oder zumindest sehr ich nicht, wo das der Fall sein könnte.

      Von einem Join ist in deinem Posting nichts zu sehen.

      Das stimmt.

        
      FROM zahlungen ze JOIN rechnungscontainer r  
      ON r.RID = ze.RID WHERE ze.Zahlungsdatum BETWEEN '2013-05-12' AND '2013-05-22'  
      AND r.RechnungenID > 3  
      
      

      Nik

      1. Korrektur:

          
        FROM zahlungen ze JOIN rechnungscontainer r  
        ON r.RID = ze.RID WHERE ze.Zahlungsdatum BETWEEN '2013-05-12' AND '2013-05-22'  
        AND r.RID > 3  
        
        

        Nik

      2. Tach!

        Wenn NULL als Ergebnis rauskommt, war irgendwo ein NULL beteiligt.
        Hab ich mal kontrolliert, ist aber nicht der Fall.

        Wie? Zum Beispiel ergibt weder ein WHERE foo = NULL noch ein WHERE foo != NULL ein Ergebnis, weil in beiden Fälle der Ausdruck zu NULL evaluiert und damit die Bedingung nicht erfüllt ist. Auf NULL kann man nur mit IS NULL oder IS NOT NULL (plus ein paar Varianten und noch ein paar weitere auf NULL spezialisierte Funktionen) testen.

        FROM zahlungen ze JOIN rechnungscontainer r ON r.RID = ze.RID

        Hmm, das ist schonmal kein Outer Join, der NULL-Ergebnisse liefern könnte. Das NULL wird dann wohl irgendwo in den Daten stecken. Du hast die Query mal anhand von überschaubar wenigen Daten auf Funktionieren gemäß Absicht geprüft? Oder lässt du sie gleich auf einen unübersichtlichen Datenhaufen los?

        dedlfix.

        1. Hmm, das ist schonmal kein Outer Join, der NULL-Ergebnisse liefern könnte. Das NULL wird dann wohl irgendwo in den Daten stecken.

          Hi,

          Zumindest nicht als Eintrag.

          Du hast die Query mal anhand von überschaubar wenigen Daten auf Funktionieren gemäß Absicht geprüft? Oder lässt du sie gleich auf einen unübersichtlichen Datenhaufen los?

          Völlig überschaubar. Der Rechnungscontainer (also Tabelle) hat 9 Datensätze (wovon 3 per WHERE-Klausel ohnehin unberücksichtigt bleiben), die Zahlungen-Tabelle hat 1 Eintrag.

          Bin leider grad nicht an meinem Rechner, sonst könnte ich Dir nen Dump schicken.

          Nik

          1. Bin leider grad nicht an meinem Rechner, sonst könnte ich Dir nen Dump schicken.

            Habs mal rekonstruiert, hier ist ein Dump, der dasselbe Ergebnis produziert.

              
            CREATE TABLE IF NOT EXISTS rechnungscontainer (  
              RechnungenID int(6) NOT NULL AUTO_INCREMENT,  
              Belegart char(2) DEFAULT 'RG',  
              PRIMARY KEY (RechnungenID)  
            ) ENGINE=MyISAM;  
              
            INSERT INTO rechnungscontainer (RechnungenID, Belegart) VALUES  
            (1, 'RG'),  
            (2, 'ST'),  
            (3, 'GU'),  
            (4, 'RG'),  
            (5, 'RG'),  
            (6, 'RG'),  
            (7, 'RG'),  
            (8, 'RG'),  
            (9, 'RG');  
              
              
            CREATE TABLE IF NOT EXISTS zahlungen (  
              zahlungenID int(6) NOT NULL AUTO_INCREMENT,  
              RechnungenID int(6) NOT NULL,  
              Nettozahlung decimal(12,2) NOT NULL,  
              USt decimal(4,2) NOT NULL,  
              Zahlungsdatum date NOT NULL,  
              PRIMARY KEY (zahlungenID)  
            ) ENGINE=MyISAM;  
              
              
            INSERT INTO zahlungen (zahlungenID, RechnungenID, Nettozahlung, USt, Zahlungsdatum) VALUES  
            (1, 7, 159.00, 19.00, '2013-05-18');  
            
            

            Und die entsprechende Query:

              
            SELECT  
            SUM(ze.Nettozahlung  
            *(CASE  
            WHEN r.Belegart = 'RE' THEN 1  
            WHEN r.Belegart = 'GU' THEN (-1)  
            WHEN r.Belegart = 'ST' THEN (-1)  
            END) ),  
            ROUND(SUM(ze.Nettozahlung*(ze.USt/100)  
            *(CASE  
            WHEN r.Belegart = 'RE' THEN 1  
            WHEN r.Belegart = 'GU' THEN (-1)  
            WHEN r.Belegart = 'ST' THEN (-1)  
            END) ),2)  
            FROM zahlungen ze  
            JOIN rechnungscontainer r ON r.RechnungenID = ze.RechnungenID  
            WHERE  
            ze.Zahlungsdatum BETWEEN '2013-05-12' AND '2013-05-22'  
            AND r.RechnungenID > 3  
            
            

            Nik

            1. Tach!

              Und die entsprechende Query:

              Wenn man bei der die SELECT-Klausel-Felder durch ein * austauscht, sieht man als Belegart was?

              CASE
              WHEN r.Belegart = 'RE' THEN 1
              WHEN r.Belegart = 'GU' THEN (-1)
              WHEN r.Belegart = 'ST' THEN (-1)
              END

              Und passt das auf einen dieser Werte?

              dedlfix.

              1. Moin!

                Tach!

                Und die entsprechende Query:

                Wenn man bei der die SELECT-Klausel-Felder durch ein * austauscht, sieht man als Belegart was?

                CASE
                WHEN r.Belegart = 'RE' THEN 1
                WHEN r.Belegart = 'GU' THEN (-1)
                WHEN r.Belegart = 'ST' THEN (-1)
                END

                Und passt das auf einen dieser Werte?

                Was einen dann dazu veranlassen sollte, solche Rechenspielchen doch lieber in der Datenbanktabelle selbst zu speichern, und nicht im Query. Dann kann man den Berechnungsfaktor (1, -1) für Rechnungen, Gutschriften und Stornos dort behandeln. Oder man schreibt das Vorzeichen tatsächlich in die gebuchte Zahlung mit hinein und addiert nur.

                Oder man macht es richtig und nutzt die Regeln der doppelten Buchführung. Dann würde der bereits bestehenden Buchung in "zahlungen" noch hinzuzufügen sein, von wem und an wen gebucht wird, also im Prinzip die beiden beteiligten Konten des Zahlungsflusses. Und dann braucht man auch keine für die Berechnung relevante Klassifikation der eigentlichen Zahlung, weil a) nur positive Geldbeträge in genau eine Richtung verschoben werden, und allein daran kann man sehen, ob der Kunde eine Rechnung bezahlt hat (Buchung von Bank auf Konto Kunde X), ob eine Bestellung getätigt wurde (Buchung von Konto Kunde X auf Lieferkonto), ob eine Bestellung und damit Rechnung storniert wurde (Buchung von Lieferkonto auf Konto Kunde X), oder ob der Kunde eine Gutschrift erhalten hat (Buchung von Gutschrift auf Konto Kunde X).

                Diese Buchhaltung mit Geldfluß ist für den Einsteiger vielleicht verwirrend, aber letztendlich logisch.

                - Sven Rautenberg

                1. Was einen dann dazu veranlassen sollte, solche Rechenspielchen doch lieber in der Datenbanktabelle selbst zu speichern, und nicht im Query.

                  Jain. Ich speichere sie in der DB so, wie ich sie für die eigentlichen Vorgänge selber brauche. Und dort sind die Stornos im Minus und die Gutschriften im Plus. Insofern stimmt natürlich die Query wieder nicht, weil die ST dann = 1 und nicht gleich (-1) sein müssen.
                  Die Konten speichere ich natürlich in der ze-Tabelle mit. Es geht hier gerade um etwas anderes, was ich berechnen möchte (geht ggf. zu weit, es zu erklären). Prinzipiell hast Du natürlich nicht ganz Unrecht.

                  Nik

              2. Wenn man bei der die SELECT-Klausel-Felder durch ein * austauscht, sieht man als Belegart was?

                Und passt das auf einen dieser Werte?

                Hi,

                aaah! Ich k.$$!!$$.tz gleich!

                Sagte ich nicht "Brett vorm Kopf"??!!

                Danke, ich habs echt nicht gesehen! :-)

                Nik

                1. Tach!

                  aaah! Ich k.$$!!$$.tz gleich!

                  Das bringt doch nichts.

                  Danke, ich habs echt nicht gesehen! :-)

                  Beim nächsten Mal, einfach mehr Kontrollausgaben machen. Mein erster Schritt war (abgesehen vom Ignorieren des ROUND-Teils), das SUM() zu entfernen, also das CASE-Ergebnis allein abzufragen: blieb NULL. Dann also auch das CASE raus, und siehe da: ein Datensatz. Wenn der nun NULL ergibt, kann das CASE kein Ergebnis liefern, also passt keine der Bedingungen und ein ELSE ist auch nicht eingebaut. (Ein ELSE nachzurüsten nützt dir aber im Fehlerfall auch nichts mehr, das verfälscht nur das Ergebnis, ohne dass du mit einer Meldung darauf hingewiesen wirst).

                  Übrigens, die Variante CASE r.Belegart WHEN 'RG' THEN 1 WHEN 'GU' THEN ... spart etwas Tipparbeit

                  dedlfix.

                  1. Beim nächsten Mal, einfach mehr Kontrollausgaben machen. Mein erster Schritt war (abgesehen vom Ignorieren des ROUND-Teils), das SUM() zu entfernen, also das CASE-Ergebnis allein abzufragen: blieb NULL.

                    Stimmt. Den Rest hatte ich auch so gemacht. Aber CASE alleine nicht.
                    Jups, danke nochmal.
                    Nik

  2. Moin,

    »» SUM(ze.Nettozahlung  
    
    > *(CASE  
    > WHEN r.Belegart  = 'RE' THEN 1  
    > WHEN r.Belegart = 'GU' THEN (-1)  
    > WHEN r.Belegart = 'ST' THEN (-1)  
    > END)  
    > ),
    
    

    Auf jeden Fall schonmal END CASE statts nur END. Unten auch.

    »» ROUND(SUM(ze.Nettozahlung*(ze.USt/100)  
    
    > *(CASE  
    > WHEN r.Belegart = 'RE' THEN 1  
    > WHEN r.Belegart = 'GU' THEN (-1)  
    > WHEN r.Belegart = 'ST' THEN (-1)  
    > END)  
    > ),2)  
    > 
    
    

    Ansonsten fällt mir nichts auf. Ohne diese Anweisungen gibt er eine Ergebnismenge größer NULL zurück, nehme ich an!?

    Grüße Marco

    --
    Ich spreche Spaghetticode - fließend.
    1. Tach!

      Auf jeden Fall schonmal END CASE statts nur END. Unten auch.

      Nein, END CASE braucht nur das Flow-Control-Statement CASE einer Stored Procedure/Function. In einem SELECT wäre etwas anderes als END ein Fehler.

      dedlfix.

  3. Hi,

    wer sieht, was ich grade nicht sehe?

    Ich sehe nicht, wie Du gruppierst.
    Aber die Verwendung von SUM deutet an, daß Du gruppierst.

    Wie wäre es, wenn Du mal zur Verdeutlichung das gesamte SQL hinschreibst und das nicht scheibchenweise machst (hier mal ein bißchen was von den selektierten Werten, da mal ein bißchen JOIN, ...)?

    Und vielleicht auch noch die Create-Statements der beteiligten Tabellen.

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.