Course / Orientation / Lesson 03

Lesson 03 · Orientation

Filter and sort through relationships

Use relationship paths in WHERE and ORDER BY, including two-hop filters and descending dates. Select only the fields you need.

1:51 · video7 scenesPrerequisites: the in-memory Python session and imported CSV data from lesson 2

Development course · Python console demonstration · API compatibility

Upcoming release preview. These lessons target the upcoming release. The current PyPI package does not yet support the complete examples. Installation verification is pending →

WATCH THE LESSON1:51 · English · AI narration
Download MP4 ↓English captions ↓

Terminal walkthrough with Heart, an AI-generated voice. Commands and results were executed on SQLite, then animated with edited timing. The complete transcript and examples are below.

Download this example ↓ · Includes four CSV files and console commands. Put the CSV files in your working folder. If Python was closed, use start-here.py to recreate lessons one and two.

Scene 01

Use the same paths in queries

Welcome back! We can already read fields through relationships. Now let us use those same paths to choose and sort records. Continue in the same console. We will use the customers and invoices we imported last time. If Python was closed, the download includes a script to rebuild that temporary dataset.

Example & screen notes
Relationship paths
columns → what to read
where → which records
order_by → in what order
Same Python session, same sample data
Closed Python? Use the lesson bundle to restart

Scene 02

Filter by the customer city

Let's find invoices for Florence. Use the customer city in where. Colon city is a parameter: its value is passed separately. We only ask to return the invoice number.

Example & screen notes
>>> invoices.query(
...     columns="$number",
...     where="@customer_id.city = :city", city="Florence",
... ).fetch()
[[number=INV-001], [number=INV-009], [number=INV-005], [number=INV-011]]

Scene 03

Sort by the customer city

Let's sort invoices by city. Use the same path in order by. Without a direction, the order is ascending. Limit keeps the displayed result short.

Example & screen notes
>>> invoices.query(
...     columns="$number, @customer_id.city",
...     order_by="@customer_id.city", limit=4,
... ).fetch()
[[number=INV-004,_customer_id_city=Amsterdam], [number=INV-008,_customer_id_city=Boston], [number=INV-001,_customer_id_city=Florence], [number=INV-005,_customer_id_city=Florence]]

Scene 04

Put the newest invoices first

Let's show the newest rows first. From an invoice row, follow its invoice to the date. Add DESC for descending order. These three rows belong to the latest invoice.

Example & screen notes
>>> rows.query(
...     columns="@invoice_id.invoice_date, $total",
...     order_by="@invoice_id.invoice_date DESC", limit=3,
... ).fetch()
[[_invoice_id_invoice_date=2026-10-09,total=12.8], [_invoice_id_invoice_date=2026-10-09,total=4.1], [_invoice_id_invoice_date=2026-10-09,total=15]]

Scene 05

Filter through two relationships

Now start from an invoice row. To reach the customer city, go through the invoice and then the customer. Let's find rows for Florence. The filter follows two relationships. The returned columns follow the product relation instead. A field used in a filter need not be selected.

Example & screen notes
invoice_row → invoice → customer
@invoice_id.@customer_id.city
>>> rows.query(
...     columns="@product_code.name, $quantity",
...     where="@invoice_id.@customer_id.city = :city",
...     city="Florence", limit=3,
... ).fetch()
[[_product_code_name=Green tea,quantity=2], [_product_code_name=Coffee,quantity=1], [_product_code_name=Mug,quantity=4]]

Scene 06

Combine filters and ordering

Let's combine the conditions. Keep Florence rows from October first, newest invoices first. City and date are parameters. Neither filtered field needs to appear in the result. The same paths work in columns, where, and order by. Let's close this read transaction. We only read the data; the imported records have not changed.

Example & screen notes
>>> rows.query(
...     columns="@product_code.name, $total",
...     where="@invoice_id.@customer_id.city = :city "
...           "AND @invoice_id.invoice_date >= :since",
...     city="Florence", since=date(2026, 10, 1),
...     order_by="@invoice_id.invoice_date DESC", limit=4,
... ).fetch()
[[_product_code_name=Green tea,total=10.5], [_product_code_name=Coffee,total=27.6], [_product_code_name=Mug,total=5.25], [_product_code_name=Tea tin,total=6.7]]
>>> db.commit()

Scene 07

Thank you — the same SQL, fewer details

Thanks for following along! Use relationship fields wherever the query needs them. Select only what you want to read, and add just the conditions and ordering you need.

Example & screen notes
Thank you!
The same paths in columns, where and order_by
Write only what the query needs