MySQL fehlerhafte Summe
mixmastertobsi
- mysql
0 dedlfix0 Rolf B0 ursus contionabundo0 mixmastertobsi1 MudGuard
0 Rolf B0 dedlfix
Hallo Zusammen,
ich möchte alle Aufträge eine Woche summieren, doch leider kommt hier das falsche Ergebnis raus, sobald noch ein paar JOINs als Abfrage-Parameter hinzufüge.
Mit SUM(distinct gesamtpreis) klappt es leider auch nicht… Aufgrund der Tatsache, dass es für einen Auftrag in der Tabelle "auftrag_ship" mehrere Einträge geben kann, wird der Datensatz doppelt summiert...aber warum?
Die Abfrage sieht in etwa so aus.
SELECT SUM(auftrag.gesamtpreis) as g1, COUNT(auftrag_rechnung.auftragnr) as value
FROM auftrag_rechnung
JOIN auftrag_info ON auftrag_info.auftragnr=auftrag_rechnung.auftragnr AND auftrag_info.status='1' AND auftrag_info.date>'2019-01-07'
JOIN auftrag_ship ON auftrag_ship.auftragnr=auftrag_rechnung.auftragnr
JOIN auftrag ON auftrag.auftragnr=auftrag_rechnung.auftragnr
Tach!
ich möchte alle Aufträge eine Woche summieren, doch leider kommt hier das falsche Ergebnis raus, sobald noch ein paar JOINs als Abfrage-Parameter hinzufüge.
Das Problem ist dann das Ermitteln der richtigen Ergebnismenge - oder das richtige Ermitteln der Ergebnismenge.
Aufgrund der Tatsache, dass es für einen Auftrag in der Tabelle "auftrag_ship" mehrere Einträge geben kann, wird der Datensatz doppelt summiert...aber warum?
Am besten mal die Query mit SELECT *
statt SUM() und COUNT() ausführen, damit du siehst, welche Daten in der Ergebnismenge sind, auf dass du sie weiter einschränken kannst, auf das was du wirklich abfragen möchtest. Es kann helfen, Joins durch Correlated Subquerys auszutauschen, besonders wenn von der gejointen Tabelle lediglich ein einzelner Wert pro Datensatz der Hauptquery erwartet wird.
Die Abfrage sieht in etwa so aus.
Nützt mir nicht viel ohne zu wissen, warum der Join erfolgt und wie die Tabellen sowie Daten aussehen.
dedlfix.
Hallo mixmastertobsi,
dann JOINe auftrag_ship doch einfach nicht. Es wird ja nichts daraus verwendet.
Wenn Du das lediglich für's Forum weggelassen hast, dann müsste man gucken was Du daraus verwendest, um raten zu können, ob ein Subselect zielführend ist.
Und Du müsstest deine Kardinalitäten genau benennen. Du zeigst 4 Tabellen: auftrag, auftrag_info, auftrag_rechnung und auftrag_ship; da müsstest Du klarstellen wie die Verhältnisse in den Relationen von auftrag zu den 3 anderen sind. 1:1 oder 1:n.
Wenn es 1:1 ist, könnte man auch fragen, warum es mehrere Tabellen sind. Wenn es 1:n ist, dürfte es außer bei auftrag_ship ggf. noch weitere Probleme geben können.
Rolf
Schritt 1 ist immer: ordentlich notieren!
Denn das hilft ungemein dabei, zu erkennen, was man eigentlich notiert hat. In Deinem Fall:
SELECT
SUM( auftrag.gesamtpreis ) as g1,
COUNT( auftrag_rechnung.auftragnr ) as value
FROM
auftrag_rechnung
JOIN
auftrag_info ON auftrag_info.auftragnr = auftrag_rechnung.auftragnr
AND auftrag_info.status = '1'
AND auftrag_info.date > '2019-01-07'
JOIN
auftrag_ship ON auftrag_ship.auftragnr = auftrag_rechnung.auftragnr
JOIN
auftrag ON auftrag.auftragnr = auftrag_rechnung.auftragnr
klappt es leider auch nicht… Aufgrund der Tatsache, dass es für einen Auftrag in der Tabelle "auftrag_ship" mehrere Einträge geben kann, wird der Datensatz doppelt summiert...aber warum?
Womöglich wegen der Art des Joins. Versuchs mal mit einem "Cross Join mit einer Beschränkung der Ergebnisse".
SELECT
SUM( `auftrag`.`gesamtpreis` ) as g1,
COUNT( `auftrag_rechnung`.`auftragnr` ) as value
FROM
`auftrag_rechnung`,
`auftrag_info`,
`auftrag_ship`,
`auftrag`
WHERE
`auftrag_info`.`auftragnr` = `auftrag_rechnung`.`auftragnr`
AND `auftrag_ship`.`auftragnr` = `auftrag_rechnung`.`auftragnr`
AND `auftrag`.`auftragnr` = `auftrag_rechnung`.`auftragnr`
AND `auftrag_info`.`status` = '1'
AND `auftrag_info`.`date` > '2019-01-07'
;
Also, das JOIN für auftrag_ship habe ich verwendet, weil MySQL NUR die Datensätze von auftrag.gesamtpreis summieren soll, welche auch einen auftrag_ship Datensatz haben.
Problem ist, dass wenn es zwei mal einen auftrag_ship Datensatz gibt, auch zwei Reihen ausgegeben werden, obwohl es auftrag_rechnung nur einmal gibt.
Ich schreibe es Euch mal vereinfacht auf…
DB-Auftrag
auftragnr | Gesamtpreis
------------------
1 | 1000
2 | 500
3 | 200
DB-Auftrag_Rechnung
id | auftragnr
------------------
1 | 1
2 | 3
DB-Auftrag_info
id | auftragnr | status | value
------------------------------
1 | 1 | 1 | 1
1 | 3 | 1 | 1
DB-Auftrag_ship
ID | auftragnr | date | ship
-------------------------
1 | 1 | 2019-01-12 | 3
1 | 1 | 2019-01-12 | 5
1 | 1 | 2019-01-12 | 3
1 | 3 | 2019-01-12 | 3
Hi,
Also, das JOIN für auftrag_ship habe ich verwendet, weil MySQL NUR die Datensätze von auftrag.gesamtpreis summieren soll, welche auch einen auftrag_ship Datensatz haben.
Dann joine das nicht, sondern frage im WHERE ab, ob ein passender Datensatz in auftrag_ship existiert.
cu,
Andreas a/k/a MudGuard
Hallo ursus,
seit wann macht es einen Unterschied, ob ich die JOIN-Bedingung mit ON oder im WHERE notiere?
(Mal abgesehen von dem Umstand, dass es gaaanz früher ON noch nicht gab)
Aber wo Du das so schön säuberlich notiert hast, sehe ich was anderes (nicht dass es Auswirkungen auf die Funktion der Query hätte, es stört nur meinen Ordnungssinn): Wenn ich eine Query formuliere, sollten die Join-Bedingungen analog zu den Relationen im Modell notiert werden. Ich nehme an, dass die auftrag-Tabelle die zentrale Tabelle ist und die anderen davon abhängig sind. Dementsprechend sollte immer gegen auftrag.auftragnr geJOINt werden.
Rolf
Tach!
Womöglich wegen der Art des Joins. Versuchs mal mit einem "Cross Join mit einer Beschränkung der Ergebnisse".
Inner Join und Cross Join sind unter MySQL gleichwertige Äquivalente zum impliziten Join, den du eigentlich meinst, also Tabellen kommasepariert und über die WHERE-Klausel verknüpft. Das erzeugt immer dasselbe kartesische Produkt.
dedlfix.