Ergänzende Anmerkungen: Weder Verbindung noch Cursor werden geschlossen. Da bietet sich ``with`` in Verbindung mit `contextlib.closing()` an.
Bei ORDER BY würde man eher keine Spaltennummer sondern den passenden Namen verwenden. Das ist verständlicher und auch robuster bei Programmänderungen da keine magische Zahl stehen zu haben an die man denken muss.
Falls das Datenbankschema noch nicht in Stein gemeisselt ist, würde ich was gegen `artikelaufbestellungen` machen — da gehören Unterstriche zwischen die Worte. IMHO noch schlechter lesbar wird das wenn der Name auf Grossbuchstaben normalisiert wird (`ARTIKELAUFBESTELLUNGEN`). SQLite3 scheint das nicht zu machen, aber das ist ja auch nicht garantiert, das zukünftige Versionen das nicht anders handhaben.
Dann sollte man auch gleich den Tabellennamen aus den Spalten in der jeweiligen Tabelle rausnehmen. Man kann sich dann bei der Abfrage den Aliasnamen sparen und es wird trotzdem ein kleines bisschen weniger Tipparbeit, ohne das man irgendwelche Informationen dadurch verliert. Durch eine Indirektion weniger wird es sogar etwas leichter verständlich.
Noch schöner wird es wenn man den sperrigen Tabellennamen `artikel_auf_bestellungen` auf `bestellung` reduziert, denn das scheint das ja letztlich zu sein. Insgesamt dann eine schön lesbare SQL-Abfrage ohne irgendwelche redundanten Informationen in den Namen oder kryptische Kürzel/Aliasnamen:
Code: Alles auswählen
SELECT artikel.beschreibung,
SUM((bestellung.menge * artikel.preis)) AS umsatz
FROM artikel
INNER JOIN bestellung ON artikel.id = bestellung.artikel_id
GROUP BY artikel.beschreibung
ORDER BY artikel.beschreibung
Bevor man sich für Tabellenausgabe selbst etwas bastelt: Es gibt da schöne Bibliotheken wie `rich` (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import sqlite3
from contextlib import closing
import rich
from rich.box import ROUNDED
from rich.table import Column, Table
from rich.text import Text
DB_FILENAME = "Sportgeschäft.db"
def main():
with closing(sqlite3.connect(DB_FILENAME)) as verbindung:
with closing(verbindung.cursor()) as cursor:
cursor.execute(
"""
SELECT artikel.beschreibung,
SUM((bestellung.menge * artikel.preis)) AS umsatz
FROM artikel
INNER JOIN bestellung
ON artikel.id = bestellung.artikel_id
GROUP BY artikel.beschreibung
ORDER BY artikel.beschreibung
"""
)
ergebnis = cursor.fetchall()
gesamt_umsatz = sum(umsatz for _, umsatz in ergebnis)
table = Table("Beschreibung", Column("Umsatz", justify="right"))
for beschreibung, umsatz in ergebnis:
table.add_row(beschreibung, f"{umsatz:.2f}")
table.rows[-1].end_section = True
table.add_row(
Text("Gesamt:", "bold", justify="right"),
Text(f"{gesamt_umsatz:.2f}", "bold underline"),
)
rich.print(table)
if __name__ == "__main__":
main()
Beispielausgabe (im Terminal sind die erste und letzte Zeile fett gedruckt und die Gesamtsumme unterstrichen):
Code: Alles auswählen
╭──────────────────┬─────────╮
│ Artikel │ Umsatz │
├──────────────────┼─────────┤
│ Tannenbaum │ 42.23 │
│ Schoko-Osterhase │ 4711.00 │
│ (gebraucht) │ │
├──────────────────┼─────────┤
│ Gesamt: │ 4753.23 │
╰──────────────────┴─────────╯