Django - Problem mit GROUP_By vs. annotate

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
noisefloor
User
Beiträge: 3876
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich würde gerne folgende SQL-Query als Django-Query haben:

Code: Alles auswählen

SELECT kdnr, kunde, sum(kosten) FROM sonderfracht
             WHERE strftime('%Y-%m-%d', vdatum) >= ?
             AND strftime('%Y-%m-%d', vdatum) <= ?
             GROUP BY kdnr
             ORDER BY SUM(kosten) DESC
bekomme ich aber nicht hin. Das Problem ist das `GROUP_BY kdnr` in Django abzubilden...

Folgender Django-Query

Code: Alles auswählen

res = Sonderfracht.objects.filter(vdatum__month=2).values('kdnr', 'kunde').annotate(summe=Sum('kosten')).order_by('-summe')
gruppiert hat nach `kdnr` _und_ `kunde` - will ich aber nicht.

Code: Alles auswählen

>>> print(res.query)
SELECT "sonderfracht_sonderfracht"."kdnr", "sonderfracht_sonderfracht"."kunde", SUM("sonderfracht_sonderfracht"."kosten") AS "summe" FROM "sonderfracht_sonderfracht" WHERE django_date_extract('month', "sonderfracht_sonderfracht"."vdatum") = 2 GROUP BY "sonderfracht_sonderfracht"."kdnr", "sonderfracht_sonderfracht"."kunde" ORDER BY "summe" DESC
Lasse ich `kunde` in `values()` weg, dann ist es auch im `SELECT` weg...

Gibt's da einen Trick bzw. wie geht das? Meine Recherche im Web war da auch erfolglos.

Gruß, noisefloor
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Das funktioniert nur weil du MySQL verwendest. Du kannst bzw darfst nicht kunde selektieren ohne danach zu gruppieren.

EDIT:// und da die kundennummer wahrscheinlich eindeutig dem kunden zuordenbar ist gibt es eigentlich keinen grund nicht nach kunde auch zu gruppieren. Mal abgesehen davon dass das Beispiel wohl einige Datenbanknormalformen verletzt :þ
EDIT2:// Und strftime ist einer der besten Wege zu verhindern dass MySQL einen Index verwendet, selbiges gilt für __month in Django.
Benutzeravatar
noisefloor
User
Beiträge: 3876
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

also die DB ist SQLite (die Version, die Python 3.4 an Bord hat)... und es funktioniert trotzdem ;-)
und da die kundennummer wahrscheinlich eindeutig dem kunden zuordenbar ist gibt es eigentlich keinen grund nicht nach kunde auch zu gruppieren. Mal abgesehen davon dass das Beispiel wohl einige Datenbanknormalformen verletzt
Das stimmt. Ist aber eine Legacy DB, die mit Absicht vom ERP-System entkoppelt ist. Von daher kann ich da so nichts gegen machen.
Und strftime ist einer der besten Wege zu verhindern dass MySQL einen Index verwendet, selbiges gilt für __month in Django.
Ah, ok. Wobei die DB klein ist und weniger als 20 Abfragen pro Monat bekommt... Werde ich mir aber für mögliche größere Projekte merken.

Ich werde dann wohl mal raw SQL-Queries benutzen. Mal sehen, wie das Ergebnis aussieht.

Gruß, noisefloor
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

noisefloor hat geschrieben: Ich werde dann wohl mal raw SQL-Queries benutzen. Mal sehen, wie das Ergebnis aussieht.
Wenn garantiert ist dass Kundennr == kunde, dann kannst du den ORM query verwenden, das Ergebnis ist das gleiche, da das 2. group_by an der Gruppe nix mehr ändert.
BlackJack

@noisefloor: Vielleicht übersehe ich ja etwas aber die SQL-Abfrage dürfte eigentlich gar nicht funktionieren, eben weil nach Kunde nicht gruppiert wird. Wie sollte denn da das Ergebnis aussehen?
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

BlackJack hat geschrieben:@noisefloor: Vielleicht übersehe ich ja etwas aber die SQL-Abfrage dürfte eigentlich gar nicht funktionieren, eben weil nach Kunde nicht gruppiert wird. Wie sollte denn da das Ergebnis aussehen?
MySQL und scheinbar auch SQLite suchen sich zufällig eine Row aus :)
Benutzeravatar
noisefloor
User
Beiträge: 3876
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@BlackJack: Das Ergebnis ist halt was man beim Query erwartet - Kd.Nr., Kundenname, Summe der Kosten, gruppiert nach Kd.Nr., sortiert nach Kosten.

Da Kd.Nr. und Kundenummer manuell eingegeben werden (diese Schwäche hatte wir ja schon weiter oben...), kann es vorkommen, das eine Kd.Nr. mehrere Kundennamen hat. SQLite (und auch MySQL) liefern dann im Ergebnis trotzdem nur einen Kundenanmen zurück (ob's das erste Vorkommen ist weiß ich nicht).

Unter Strich ist es dann aber offensichtlich nicht-korrekte SQL und ich darf glücklich sein, dass es bisher trotzdem funktioniert hat ;-)

Werde dann mal überlegen, wie ich das in Zukunft mache...

Gruß, noisefloor
Antworten