在使用Python和SQLAlchemy与PostgreSQL数据库的原型应用程序中,我有以下架构(摘录):
class Guest(Base):
__tablename__ = 'guest'
id = Column(Integer, primary_key=True)
name = Column(String(50))
surname = Column(String(50))
email = Column(String(255))
[..]
deleted = Column(Date, default=None)
我想使用SQLAlchemy构建一个查询,该查询检索要在后台显示的来宾列表。
为了实现分页,我将使用LIMIT和OFFSET,以及COUNT(*)OVER()来获取执行查询时的记录总量(不使用不同的查询)。
SQL查询的示例可以是:
SELECT id, name, surname, email,
COUNT(*) OVER() AS total
FROM guest
WHERE (deleted IS NULL)
ORDER BY id ASC
LIMIT 50
OFFSET 0
如果我使用SQLAlchemy构建查询,我可以这样做:
query = session.query(Guest)
query = query.filter(Login.deleted == None)
query = query.order_by(Guest.id.asc())
query = query.offset(0)
query = query.limit(50)
result = query.all()
如果我想计算来宾表中的所有行,我可以这样做:
from sqlalchemy import func
query = session.query(func.count(Guest.id))
query = query.filter(Login.deleted == None)
result = query.scalar()
现在我要问的问题是如何使用SQLAlchemy执行一个单独的查询,类似于上面的那个,一石二鸟(返回前50行和总行数来构建分页链接,所有在一个查询中)。
有趣的是使用window functions in PostgreSQL,它允许上述行为,从而使您不必再查询两次而只需查询一次。
可能吗?
提前致谢。
所以我在SQLAlchemy文档中找不到任何示例,但我找到了这些函数:
[count()][1]
[over()][1]
[label()][1]
我设法将它们组合起来以产生我正在寻找的结果:
from sqlalchemy import func
query = session.query(Guest, func.count(Guest.id).over().label('total'))
query = query.filter(Guest.deleted == None)
query = query.order_by(Guest.id.asc())
query = query.offset(0)
query = query.limit(50)
result = query.all()
干杯!
附:我也发现这个question on Stack Overflow,没有得到答复。