Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy: Return a record filtered by max value of a column

All, I'm having an issue with a SQLA request; the goal is to return a record with the maximum value in the counter column:

this works fine - returns proper record:

m=12 # arbitrary example of a max value of counter = 12
qry = session.query(Data).
      filter(Data.user_id == user_id,Data.counter == m)

The code below does not work- returns None:

from sqlalchemy import func
qry = session.query(Data).
      filter(Data.user_id == user_id,
      Data.counter == func.max(Data.counter).select())

Note that there's never more than one record with a maximum value (if that's relevant).

Surely there's a way to return a record having the max value in one of the columns. Any Ideas?

like image 580
GG_Python Avatar asked Jun 11 '15 15:06

GG_Python


People also ask

What is difference between filter and filter by in SQLAlchemy?

The second one, filter_by(), may be used only for filtering by something specifically stated - a string or some number value. So it's usable only for category filtering, not for expression filtering. On the other hand filter() allows using comparison expressions (==, <, >, etc.)

What does an SQLAlchemy query return?

It returns exactly one result or raise an exception. It applies one or more ORDER BY criterion to the query and returns the newly resulting Query. It performs a bulk update query and updates rows matched by this query in the database.

How do I select a column in SQLAlchemy?

SQLAlchemy Core The already created students table is referred which contains 4 columns, namely, first_name, last_name, course, score. But we will be only selecting a specific column. In the example, we have referred to the first_name and last_name columns. Other columns can also be provided in the entities list.

What is subquery in SQLAlchemy?

The grouping is done with the group_by() query method, which takes the column to use for the grouping as an argument, same as the GROUP BY counterpart in SQL. The statement ends by calling subquery() , which tells SQLAlchemy that our intention for this query is to use it inside a bigger query instead of on its own.


1 Answers

It sounds like you could simply sort by counter in descending order and take the first result...

from sqlalchemy import desc

qry = session.query(Data).filter(
      Data.user_id == user_id).order_by(
      desc(Data.counter).limit(1)

However if you're concerned about sorting a large dataset, you could use a subquery...

subqry = session.query(func.max(Data.counter)).filter(Data.user_id == user_id)
qry = session.query(Data).filter(Data.user_id == user_id, Data.counter == subqry)

The sql that qry would essentially be...

SELECT * 
FROM data 
WHERE data.user_id = :user_id AND data.counter = (
    SELECT max(data.counter) AS max_1 
    FROM data 
    WHERE data.user_id = :user_id GROUP BY data.user_id
);
like image 75
dekim Avatar answered Oct 09 '22 05:10

dekim