首页 > 解决方案 > 如何使用 SQLAlchemy 进行此查询

问题描述

我有一个基本查询,需要为位置添加一个过滤器。

Location.parents是一个整数数组。

它有效,但它使用 2 个查询:


parents_ids = self._db_session.query(Location.parents)\
    .filter(Location.id == location_id)\
    .scalar()

query = query.filter(
    or_(
        BookingItem.location_id == location_id, 
        BookingItem.location_id.in_(parents_ids)
    )
)

我怎样才能用一个查询来做到这一点?我尝试使用子查询,但它不起作用。


parents_ids = self._db_session.query(Location.parents)\
    .filter(Location.id == location_id)\
    .subquery()

query = query.filter(
    or_(
        BookingItem.location_id == location_id, 
        BookingItem.location_id.in_(parents_ids.as_scalar())
    )
)

标签: pythonpostgresqlsqlalchemy

解决方案


如果您希望 SQL 看起来像这样:

SELECT id
FROM booking_item
WHERE location_id = ?
   OR (SELECT location_id = ANY(parents) FROM location WHERE id = ?)

那么相关的 SQLAlchemy 将是

parents_ids = self._db_session\
    .query(BookingItem.location_id == Location.parents.any())\
    .filter(Location.id == location_id)\
    .subquery()

query = query.filter(
    or_(
        BookingItem.location_id == location_id, 
        parents_ids.as_scalar()
    )
)

另一个选项是用于UNNEST创建选项列表:

SQL:

SELECT id
FROM booking_item
WHERE location_id = ?
   OR location_id IN (SELECT UNNEST(parents) FROM location WHERE id = ?)

那么相关的 SQLAlchemy 将是

parents_ids = self._db_session\
    .query(func.unnest(Location.parents))\
    .filter(Location.id == location_id)\
    .subquery()

query = query.filter(
    or_(
        BookingItem.location_id == location_id, 
        BookingItem.location_id.in_(parents_ids.as_scalar())
    )
)

推荐阅读