Используйте SQLAlchemy, чтобы выбрать только одну строку из связанной таблицы

Обновить

November 2018

Просмотры

2.2k раз

4

Скажем, у меня есть таблица Автора и таблица Post, и каждый автор может иметь несколько сообщений.

Теперь, с помощью одного запроса SQLAlchemy, я хочу , чтобы все мои активных авторов и самый последнего опубликованное сообщения для каждого.

Я пытался пойти на это, получив список сообщений, которые joinedload Автора, используя подзапрос, чтобы сгруппировать результаты вместе, как это:

subquery = DBSession.query(Author.id, func.max(Post.publish_date).label("publish_date")) \
    .join(Post.author) \
    .filter(Post.state == 'published') \
    .filter(Author.state == 'active') \
    .group_by(Author.id) \
    .subquery()

query = DBSession.query(Post) \
    .options(joinedload(Post.author)) \
    .join(Post.author) \
    .join(subquery, and_(Author.id == subquery.c.id, 
                         Post.publish_date == subquery.c.publish_date))

Но если у меня есть два сообщения от Автора с тем же PUBLISH_DATE, и те самые новые сообщения, это означает, что я получаю, что Автор, появляющийся два раза в списке результатов. И в то время как я мог бы использовать второй подзапрос для устранения простофили (взять func.max (Post.id)), который, похоже, на самом деле, на самом деле неправильный путь об этом. Есть ли лучший способ пойти по этому поводу?

(Опять же, я ищу одного запроса, так что я пытаюсь избежать запросов на столе Автор, а затем циклически и делать сообщения запроса для каждого автора в моих результатах.)

1 ответы

6

Я хотел бы сделать это следующим образом:

LastPost = aliased(Post, name='last')
last_id = (
    session.query(LastPost.id)
    .filter(LastPost.author_id == Author.id)
    .order_by(LastPost.publish_date.desc())
    .order_by(LastPost.id.desc())
    .limit(1)
    .correlate(Author)
    .as_scalar()
)

query = (
    DBSession.query(Author, Post)
    .outerjoin(Post, Post.id == last_id)
)

for author, last_post in query:
    print(author, last_post)

Как вы можете видеть, результат является tupleпар (Author, LastPost).
Изменение outerjoinк , joinесли вы хотите только авторы , которые имеют по крайней мере один Post.
Кроме того , я не поджать никакого отношения , Author.postчтобы избежать путаницы.

van

Связанные вопросы