mysql Brett vorm Kopf
Nik
- datenbank
0 dedlfix0 misterunknown0 dedlfix
0 MudGuard
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
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.
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
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
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.
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
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
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.
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)
ENDUnd 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
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
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
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.
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
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
Tach!
Auf jeden Fall schonmal
END CASE
statts nurEND
. 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.
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