Scene 01
What we'll learn in this lesson
Welcome back! Here's what we'll learn. Turn invoice rows into one sales summary per city. Then filter individual rows with where and whole groups with having. We will focus on building the query; result formats and file exports have their own next lesson.
Scene 02
Group invoice rows by customer city
Let's total sales by city. City is the alias from lesson four. Group by puts rows from the same city together. Sum adds their calculated amounts. We get one summary per city, not one result per invoice row. Let's name the report columns. We just ran without aliases. Here, optional AS labels make the report easier to read: sales and row count. Count measures invoice rows, not customers or units sold. The database still holds all thirty-six original rows.
Example & screen notes
>>>
>>> ######## Total sales by city ########
>>>
>>> rows = db.table("shop.invoice_row")
>>> products = db.table("shop.product")
>>> rows.query(
... columns="$city, SUM($calculated_total)",
... group_by="$city", order_by="$city", limit=3,
... ).fetch()
[[city=Amsterdam,SUM__calculated_total_=26.2], [city=Boston,SUM__calculated_total_=57.8], [city=Florence,SUM__calculated_total_=300.65000000000003]]
>>>
>>> ######## Name the report columns ########
>>>
>>> report = rows.query(
... columns="$city, ROUND(SUM($calculated_total), 2) AS sales, "
... "COUNT(*) AS row_count",
... group_by="$city", order_by="$city",
... )
>>> report.fetch()
[[city=Amsterdam,sales=26.2,row_count=3], [city=Boston,sales=57.8,row_count=3], [city=Florence,sales=300.65,row_count=12], [city=Helsinki,sales=57.2,row_count=6], [city=London,sales=189.7,row_count=6], [city=Manchester,sales=87.4,row_count=3], [city=New York,sales=96.3,row_count=3]]
Scene 03
Filter rows first and groups afterwards
Let's filter rows and groups. Where keeps individual rows priced at least five before grouping. Having then keeps cities whose remaining sales reach one hundred. Florence and London qualify. Both thresholds are parameters.
Example & screen notes
>>>
>>> ######## Filter rows and groups ########
>>>
>>> selected = rows.query(
... columns="$city, ROUND(SUM($calculated_total), 2) AS sales",
... where="$unit_price >= :min_price", min_price=5,
... group_by="$city",
... having="SUM($calculated_total) >= :min_sales", min_sales=100,
... order_by="$city",
... )
>>> selected.fetch()
[[city=Florence,sales=278.65], [city=London,sales=156.6]]
>>> db.commit()
Scene 04
Thank you — from rows to groups
Thanks for following along! We turned detail rows into city summaries, then separated filtering before and after grouping. Keep this report query ready. In the next lesson, we will choose how to fetch its results in Python and export them to files.