Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy Group By With Full Child Objects

Imagine the following Media table:

| site       | show_id | time |
| ---------------------|-------|
| CNN        | 1       | 'a'   |
| ABC        | 2       | 'b'   |
| ABC        | 5       | 'c'   |
| CNN        | 3       | 'd'   |
| NBC        | 4       | 'e'   |
| NBC        | 5       | 'f'   |
--------------------------------

I would like to iterate over query results grouped by show_id and have tried this query:

listings = session.query(Media).filter(Media.site == "CNN").group_by(Media.show_id).all()

Here's how I would like to iterate over the results:

for showtimes in listings:
    for show in showtimes:
        print(show.time)

But that query doesn't give me all of the grouped child objects. What am I missing?

like image 478
Raj Avatar asked Oct 10 '18 01:10

Raj


1 Answers

In SQL the GROUP BY clause condenses the grouped rows into a single row, based on the grouping expressions. My guess is that you are using SQLite, or an older version of MySQL, since you are allowed to select non-aggregates without them being functionally dependent on the grouping expressions. The results contain values from an unspecified row per group in that case, which is seldom — if ever — useful.

A solution is to ORDER BY instead of GROUP BY in SQL and then group in Python based on the order expressions:

from itertools import groupby
from operator import attrgetter

listings = session.query(Media).\
    filter(Media.site == "CNN").\
    order_by(Media.show_id).\
    all()

# Materialize the subiterators to lists
listings = [list(g) for k, g in groupby(listings, attrgetter('show_id'))]
like image 118
Ilja Everilä Avatar answered Oct 02 '22 22:10

Ilja Everilä